/usr/local/CPAN/Audio-SndFile/Makefile.PL


# Audio::SndFile - perl glue to libsndfile
#
# Copyright (C) 2006 by Joost Diepenmaat, Zeekat Softwareontwikkeling
#
# 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

use 5.006;
use strict;
use warnings;
use ExtUtils::MakeMaker;
use Config;
$|=1;
print "Testing for pkg-config...\n";

system("pkg-config --version") and die "You don't have pkg-config installed.
You can get pkg-config at http://pkgconfig.freedesktop.org/wiki/
";


print "Testing for sndfile via pkg-config...";
system("pkg-config sndfile") and die "
Can't find sndfile development files not installed.
Please make sure you've installed libsndfile and libsndfile-dev

Recent linux distributions should have them as packages. Otherwise,
you can find libsndfile at http://www.mega-nerd.com/libsndfile/

";
print "ok\n";

my $sndversion = `pkg-config --modversion sndfile`;
my ($major,$medium,$minor) = split /\./,$sndversion;
die "This module is made for libsndfile versions 1.X.X. You have $sndversion\n" if ($major != 1);

chomp(my $flags = `pkg-config --cflags --libs sndfile`);
chomp(my $inc = `pkg-config --cflags sndfile`);
chomp(my $libs = `pkg-config --libs sndfile`);


warn "According to pkg-config, LIBS should be '$libs' and INC should be '$inc'\n";

BEGIN {
    require 'lib/Audio/SndFile/Constants.pm';
}

my $boiler = <<BOILER;
 ##########################################################################
 # This file is generated by Makefile.PL and should not be edited by hand #
 ##########################################################################
BOILER

print "Testing for enums\n";

# note: you cannot test for enums using the preprocessor, so
# create a short program for each enum we know about and see if
# it compiles. this might fail if $Config{cc} needs any additional 
# flags besides the ones from pkg-config to build and link an executable.

# also, it's pretty slow

# also also, we probably need something like this for the newer functions
# unless they're better documented than the enums :P

my $cc = "$Config{cc} $flags";
my $redir = "";
if (-e "/dev/null") {
# assume unix type redirection (not needed but makes the output a lot cleaner)
    $redir = " >/dev/null 2>&1";
}

my @not_found;
open F,">","constants.xs" or die "Can't write constants.xs: $!";
print F $boiler;
for (@Audio::SndFile::Constants::EXPORT_OK) {
    print "$_ ...";
    open C,">test.c" or die "Can't write test.c: $!";
    print C qq(
#include <sndfile.h>
#include <stdio.h>
int main() {
        printf("%d\\n",$_);
}
);
    close C;
    if (system("$cc test.c$redir") == 0) {
        print "found\n";
        print F qq(
int
$_()
    CODE:
    RETVAL = $_;
    OUTPUT:
    RETVAL
);
    }
    else {
        print "not found\n";
        push @not_found,$_;
    }
}
close F;
print "\n";
if (@not_found) {
    print "You are missing @not_found.\n";
    if (grep { !/^SF_FORMAT_/ } @not_found) {
        print "You are missing some expected constants.
If building this module fails, you might want to upgrade to a more 
recent version of libsndfile
";
    }
    else {
        print "Some filetypes are not supported by your version of libsndfile.
Otherwise you will probably be alright.
";
    }
}
else {
    print "Good. You've got all formats I know about\n";
}

my %nf = map { $_ => 1 } @not_found;
my (@define,@fnotfound);

print "Testing functions...\n";
my %test_functions = (
    sf_write_sync => "sf_write_sync(&sndfile);"
);
for (sort keys %test_functions) {
    print "$_...";
    open C,">test.c" or die "Can't write test.c: $!";
    print C qq{
#include <sndfile.h>
#include <stdio.h>
int main() {
        SNDFILE sndfile;
        $test_functions{$_}
}
        };
    close C;
    if (system("$cc test.c$redir") == 0) {
        print "found\n";
        push @define,"-D$_=$_";
    }
    else {
        push @fnotfound,$_;
        print "not found\n";
    }
}

my (@cfound, @cnotfound);
print "Testing for commands...\n";
for (qw(SFC_GET_LOG_INFO SFC_CALC_SIGNAL_MAX SFC_CALC_NORM_SIGNAL_MAX SFC_CALC_MAX_ALL_CHANNELS
        SFC_CALC_NORM_MAX_ALL_CHANNELS SFC_GET_SIGNAL_MAX SFC_GET_MAX_ALL_CHANNELS
        SFC_SET_NORM_FLOAT SFC_SET_NORM_DOUBLE SFC_GET_NORM_FLOAT SFC_GET_NORM_DOUBLE
        SFC_SET_SCALE_FLOAT_INT_READ SFC_GET_SIMPLE_FORMAT_COUNT SFC_GET_SIMPLE_FORMAT
        SFC_GET_FORMAT_INFO SFC_GET_FORMAT_MAJOR_COUNT SFC_GET_FORMAT_MAJOR SFC_GET_FORMAT_SUBTYPE_COUNT
        SFC_GET_FORMAT_SUBTYPE SFC_SET_ADD_PEAK_CHUNK SFC_UPDATE_HEADER_NOW SFC_SET_UPDATE_HEADER_AUTO
        SFC_FILE_TRUNCATE SFC_SET_RAW_START_OFFSET SFC_SET_CLIPPING SFC_GET_CLIPPING
        SFC_GET_EMBED_FILE_INFO)) {
    print "$_...";
    open C,">test.c" or die "Can't write test.c: $!";
    print C qq(
#include <sndfile.h>
#include <stdio.h>
int main() {
        printf("$_=%d\\n",$_);
        return 0;
}
);
    close C;
    if (system("$cc test.c$redir") == 0) {
        print "found\n";
        push @define,"-D$_=$_";
        push @cfound,$_;
    }
    else {
        print "not found\n";
        push @cnotfound,$_;
    }
}

print "\nSupported types: ",(join(", ",map { s/^SF_FORMAT_//; lc $_ } 
    grep { !$nf{$_} } @Audio::SndFile::Constants::FORMAT_TYPES) || "*none*") ,"\n";

print "Supported subtypes: ",(join(", ",map { s/^SF_FORMAT_//; lc $_ } 
    grep { !$nf{$_} } @Audio::SndFile::Constants::FORMAT_SUBTYPES) || "*none*") ,"\n";

print "Supported commands: ",(join(", ", map { s/SFC_//; lc($_) } @cfound) || "*none*"),"\n\n";

print "Unsupported types: ",(join(", ",map { s/^SF_FORMAT_//; lc $_ } 
    grep { $nf{$_} } @Audio::SndFile::Constants::FORMAT_TYPES) || "*none*" ),"\n";
print "Unsupported subtypes: ",(join(", ",map { s/^SF_FORMAT_//; lc $_ } 
    grep { $nf{$_} } @Audio::SndFile::Constants::FORMAT_SUBTYPES) || "*none*"),"\n";

if (@fnotfound) {
    print "Unsupported misc. functions: ",join(", ",@fnotfound),"\n";
}
else {
    print "Misc. functions all supported\n";
}
if (@cnotfound) {
    print "Unsupported commands: ",join(", ", map { s/SFC_//; lc $_ } @cnotfound),"\n";
}
else {
    print "All commands supported.\n";
}
#
# save me from repetitive coding. 
# 

open F,">","functions.xs" or die "Can't write functions.xs: $!";
print F $boiler;
for my $type (qw(short int float double)) {
    print F qq(
unsigned long
read_$type(self, buff, len)
        SNDFILE* self
        SV* buff
        unsigned long len
        PREINIT:
        unsigned long blen;
        $type* realbuffer;
        CODE:
        if (SvPOK(buff)) {
                SvPOK_only(buff);
        }
        else {
                SvPV_force(buff,PL_na);
        }
        blen = ((len * sizeof($type)) +1);
        realbuffer = ($type *) SvGROW(buff, blen);
        RETVAL = (unsigned long) sf_read_$type(self, realbuffer,len);
        SvCUR_set(buff,(STRLEN) (RETVAL * sizeof($type)));
        OUTPUT:
        RETVAL

sf_count_t
readf_$type(self, buff, len)
        Audio_SndFile self
        SV* buff
        sf_count_t len
        CODE:
        if (SvPOK(buff)) {
                SvPOK_only(buff);
        }
        else {
                SvPV_force(buff,PL_na);
        }
        RETVAL = sf_readf_$type(self->sndfile, ($type*)SvGROW(buff, self->info->channels * len * sizeof($type) + 1), len);
        SvCUR_set(buff,RETVAL * sizeof($type) * self->info->channels);
        OUTPUT:
        RETVAL

sf_count_t
write_$type(self, buff)
        SNDFILE* self
        SV* buff
        CODE:
        RETVAL = sf_write_$type(self, ($type*) SvPV_nolen(buff), SvCUR(buff) / sizeof($type));
        OUTPUT:
        RETVAL

sf_count_t
writef_$type(self, buff)
        Audio_SndFile self
        SV* buff
        CODE:
        RETVAL = sf_writef_$type(self->sndfile, ($type*) SvPV_nolen(buff), SvCUR(buff) / (sizeof($type) * self->info->channels));
        OUTPUT:
        RETVAL
);
}
for (qw(title copyright software artist comment date)) {
    print F qq(
const char* 
get_$_(self)
        SNDFILE* self
        CODE:
        RETVAL = sf_get_string(self,SF_STR_\U$_\E);
        OUTPUT:
        RETVAL

void
set_$_(self, $_)
        SNDFILE* self
        const char* $_
        CODE:
        sf_set_string(self, SF_STR_\U$_\E, $_);
);
}

for(qw(calc_signal_max calc_norm_signal_max)) {
    print F qq(

#ifdef SFC_\U$_\E

double
$_(self)
        SNDFILE* self
        CODE:
        if (sf_command( self, SFC_\U$_\E, &RETVAL, sizeof(RETVAL)) != 0) croak("Error calculating $_");
        OUTPUT:
        RETVAL

#endif
);
}

#for(qw(calc_signal_max_all_channels calc_norm_signal_max_all_channels)) {
#    print F qq(
#void
#$_(self)
#    Audio_SndFile self
#    CODE:
#    if (sf_command( self->sndfile, SFC_\U$_\E, self->datas, sizeof(self->datas)) != 0) croak("Error calculating $_");
#    return_datas(self);
#);
#
#}
1;

WriteMakefile(
    NAME              => 'Audio::SndFile',
    VERSION_FROM      => 'lib/Audio/SndFile.pm', # finds $VERSION
    PREREQ_PM         => {}, # e.g., Module::Name => 1.1
    ($] >= 5.005 ?     ## Add these new keywords supported since 5.005
      (ABSTRACT_FROM  => 'lib/Audio/SndFile.pm', # retrieve abstract from module
       AUTHOR         => 'Joost Diepenmaat <jdiepen@cpan.org>') : ()),
    LIBS              => [$libs], # e.g., '-lm'
    DEFINE            => join(" ",@define), # e.g., '-DHAVE_SOMETHING'
    INC               => "-I. $inc", # e.g., '-I. -I/usr/include/other'
	# Un-comment this if you add C files to link with later:
    # OBJECT            => '$(O_FILES)', # link all the C files too
);