#!/usr/bin/perl
# 
# List the contents of AKAI S1000/S3000 disk.
# Copyright (c) 1997, Hiroyuki Ohsaki.
# All rights reserved.
# 
# $Id: akailist,v 1.2 1998/06/30 01:35:20 oosaki Exp ohsaki $
# 

# 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 2 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

use Synth::AkaiDisk qw(qualify_path unqualify_path join_path);
use Getopt::Std;
use File::Basename;
use integer;
use strict;

my %ID = (1   => 'S1000 VOLUME',
	  3   => 'S3000 VOLUME',
	  100 => 'DRUM SETTING',
	  115 => 'S1000 SAMPLE',
	  113 => 'QLIST',
	  112 => 'S1000 PROGRAM',
	  120 => 'EFFECTS',
	  237 => 'MULTI',
	  240 => 'S3000 PROGRAM',
	  243 => 'S3000 SAMPLE');

sub show_entry {
    my($disk, $path, %entry) = @_;
    
    if ($::opt_u) {
	$path = unqualify_path($path);
    } else {
	$path = basename($path);
    }

    if ($::opt_l) {
	printf "%-14s %9d %9d %s\n",
	($ID{$entry{type}} || 'UNKNOWN'), $entry{start}, $entry{size}, $path;
    } else {
	print "$path\n";
    }
}

sub usage {
    my $prog = basename($0);
    die <<EOF;
usage: $prog [-luR] [-f file] [-p part] [path...]
 -l       list in long format
 -u       list file names in UNIX format
 -R       traverse all subdirectories recursively
 -f file  specify Akai disk image (default \$AKAI_DISK)
 -p part  read from part-th partition (default 1)
EOF
}

getopts('luRf:p:') || usage;

my $file = $::opt_f || $ENV{AKAI_DISK} || '/dev/mo';
my $part = $::opt_p || 1;

my $disk = new Synth::AkaiDisk($file, $part) || die "new: $file: $!\n";

@ARGV || push(@ARGV, '/');
while (@ARGV) {
    # read file properties
    my $path = shift;
    $path = qualify_path($path);
    (my %entry = $disk->stat($path)) || die "stat: $path: $!\n";

    # if $path is a directory, list all files in it
    if ($entry{type} == 1 or $entry{type} == 3) {	
	my(%entries) =  $disk->readdir($path);
	print "$path:\n" if (!$::opt_u);
	my $key;
	for $key (sort { $entries{$a}->{at} <=> $entries{$b}->{at} }
		  keys %entries) {

	    my %entry = %{$entries{$key}};

	    # traverse all subdirectories if -R is set
	    if ($::opt_R) {
		if ($entry{type} == 1 or $entry{type} == 3) {
		    push(@ARGV, join_path($path, $key));
		}
	    }

	    show_entry($disk, join_path($path, $key), %entry);
	}
	print "\n" if (!$::opt_u and (@ARGV > 0));
    } else {
	show_entry($disk, $path, %entry);
    }
}

__END__

=head1 NAME

akailist - List the contents of Akai S1000/S3000 HDD/CD-ROM

=head1 SYNOPSIS

  akailist [-luR] [-f file] [-p partition] [path...]

=head1 DESCRIPTION

This manual page documents B<akailist>.  This program lists the
contents of HDD/CD-ROM in Akai S1000 or S3000 format as like the
I<ls(1)> command in UNIX systems.  By default, B<akailist> lists names
of files located at I<path>.  If I<path> is a directory (or volume in
Akai terminology), B<akailist> lists all files in I<path>.  If no
I<path> is supplied, all files in the root directory are listed.

The notation of pathname, I<path>, in B<akailist> (and all other
utilities of B<akaitools>)is almost equivalent to that of conventional
UNIX systems.  For example, the pathname

  /VOLUME 001/STRING SECT

represents the file named F<STRING SECT> in the directory (or volume)
of F<VOLUME 001>.  Since shells in UNIX systems interpret space
characters as word separators, you should usually surround the
pathname with single quotes such as

  '/VOLUME 001/STRING SECT'

Otherwise, the above pathname is considered as three different names
(i.e., F</VOLUME>, F<001/STRING> and F<SECT>).  To avoid this,
B<akailist> allows users to use underscores instead of spaces.
Thus, the above pathname
can be written as

  /volume_001/string_sect

Note that the pathname is case-insensitive in B<akailist>.

=head1 OPTIONS

=over 4

=item C<-l>

In addition to the file name, file type, file location (in blocks),
and file size (in bytes) are also displayed.

=item C<-u>

All uppercase characters are changed to lowercase, and all spaces are
replaced by underscore.  This options is designed to use with standard
UNIX commands. See L<EXAMPLES>.

=item C<-R>

All directories including subdirectories are listed recursively.  

=item C<-f> file

Specify the regular file of Akai disk image or the block device file
of Akai HDD/CD-ROM.  Usually, this should be the block device of HDD
or CD-ROM such as F</dev/sda>.  If this option is omitted, the
environment variable I<AKAI_DISK> is used as the default device.  If
I<AKAI_DISK> is not defined, F</dev/mo> is assumed.

=item C<-p> partition

Specify the partition number for which B<akailist> works.  The first
partition is 1.  By default, the first partition is used.

=back

=head1 EXAMPLES

This section shows several example usage of B<akailist>.

=over 4

=item - List files in the directory F<ACOUSTIC PNO>.

  akailist /acoustic_pno

=item - See the file type and size of F</ACOUSTIC PNO/GRAND PIANO>.

  akailist -l /acoustic_pno/grand_piano

=item - List all files in the CD-ROM attached at F</dev/cdrom>.

  akailist -R -f /dev/cdrom

=item - Find all sample files in the HDD attached at F</dev/sda>.

  akailist -ulR -f /dev/sda | grep SAMPLE | awk '{ print $NF }'

=back

=head1 SEE ALSO

akaitools(1), akaiformat(1), akailist(1), akaimkdir(1), akairead(1),
akaiwrite(1), epslist(1), epsread(1), eps2akai(1), wav2akai(1),
any2akai(1), akaiconv(1) 

=head1 AUTHOR

Hiroyuki Ohsaki <ohsaki@lsnl.jp>

=cut

