# 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 = <","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 #include 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 #include 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 #include 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 ') : ()), 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 );