From 17b6af64171d90e09be1316e4df96be1f87257dd Mon Sep 17 00:00:00 2001 From: Chris Moeller Date: Sun, 20 Oct 2013 20:06:14 -0700 Subject: [PATCH] Updated WavPack to 4.70.0, and this time around, updated the project preprocessor macro definitions and moved them out of the compiler command line arguments --- Frameworks/WavPack/Files/AUTHORS | 3 + Frameworks/WavPack/Files/ChangeLog | 315 ++++ Frameworks/WavPack/Files/Makefile.am | 32 - Frameworks/WavPack/Files/README | 9 +- Frameworks/WavPack/Files/autogen.sh | 7 - Frameworks/WavPack/Files/configure.ac | 135 -- Frameworks/WavPack/Files/depcomp | 589 ------- Frameworks/WavPack/Files/install-sh | 323 ---- Frameworks/WavPack/Files/license.txt | 2 +- Frameworks/WavPack/Files/md5.c | 2 +- Frameworks/WavPack/Files/missing | 367 ----- Frameworks/WavPack/Files/pack.c | 2 +- Frameworks/WavPack/Files/tags.c | 137 +- Frameworks/WavPack/Files/unpack3.c | 42 +- Frameworks/WavPack/Files/utils.c | 68 +- Frameworks/WavPack/Files/utils.h | 6 + Frameworks/WavPack/Files/wavpack.c | 1364 +++++++++++++++-- Frameworks/WavPack/Files/wavpack.pc.in | 11 - Frameworks/WavPack/Files/wavpack_local.h | 33 +- Frameworks/WavPack/Files/wavpack_version.h | 6 +- Frameworks/WavPack/Files/words.c | 77 +- Frameworks/WavPack/Files/wputils.c | 33 +- Frameworks/WavPack/Files/wvunpack.c | 363 +++-- .../WavPack/WavPack.xcodeproj/project.pbxproj | 59 +- 24 files changed, 2127 insertions(+), 1858 deletions(-) delete mode 100644 Frameworks/WavPack/Files/Makefile.am delete mode 100755 Frameworks/WavPack/Files/autogen.sh delete mode 100644 Frameworks/WavPack/Files/configure.ac delete mode 100755 Frameworks/WavPack/Files/depcomp delete mode 100755 Frameworks/WavPack/Files/install-sh delete mode 100755 Frameworks/WavPack/Files/missing delete mode 100644 Frameworks/WavPack/Files/wavpack.pc.in diff --git a/Frameworks/WavPack/Files/AUTHORS b/Frameworks/WavPack/Files/AUTHORS index e69de29bb..68ad65a3d 100644 --- a/Frameworks/WavPack/Files/AUTHORS +++ b/Frameworks/WavPack/Files/AUTHORS @@ -0,0 +1,3 @@ +David Bryant +Sebastian Dröge +Joachim Henke diff --git a/Frameworks/WavPack/Files/ChangeLog b/Frameworks/WavPack/Files/ChangeLog index a8e47ee05..4fca6114c 100644 --- a/Frameworks/WavPack/Files/ChangeLog +++ b/Frameworks/WavPack/Files/ChangeLog @@ -1,8 +1,323 @@ + --------------------------------- + Release 4.70.0 - October 19, 2013 + --------------------------------- + + wavpack.exe (command-line encoder) - 4.70.0 + ------------------------------------------- + added: transcoding from existing WavPack files (with tag copy) + added: option to verify WavPack file integrity on creation (-v) + added: use temporary files for safer overwriting + added: detect UTF-16LE encoding for tag text files (mostly a Windows thing) + added: --version command to write machine-parsable value + added: option to allow up to 16 MB APEv2 tag data (--allow-huge-tags) + added: allow channel-order specification on WAV files with zeroed channel mask + added: several Windows features to Linux (clean ^C handling, console title) + added: 4GB file support on 32-bit Linux targets + + WavPack Library Source Code - 4.70.0 + ------------------------------------ + fixed: seeking to last block failure (after finishing file) + fixed: memcpy() not always used correctly (Linux targets) + fixed: unsigned char issue (ARM targets) + fixed: add binary tag functions to Windows DLL exports (forgot on 4.60) + added: read-only access to APEv2 tags that come at the beginning of files + improved: switched to Microsoft Visual Studio 2008 (win32 only) + + wvunpack.exe (command-line decoder) - 4.70.0 + -------------------------------------------- + added: use temporary files for safer overwriting + added: --version command to write machine-parsable value + added: new command (-f) for getting machine-parsable WavPack file info + added: option (-n) to suppress audio decoding (useful for extracting only tags) + + wvgain.exe (command-line ReplayGain scanner) - 4.70.0 + ----------------------------------------------------- + fixed: the -q (quiet) option would cause the -c (clean) option to fail + added: version command (-v) to write machine-parsable value + + in_wv.dll (winamp plugin) - 2.8 + ------------------------------- + fixed: settings could not be saved on newer Windows versions (7 & 8) + fixed: installation issue caused by including manifest in build + added: dialog to installer suggesting "Winamp Essentials Pack" + + + -------------------------- + Update - December 23, 2009 + -------------------------- + + in_wv.dll (winamp plugin) - 2.8a + -------------------------------- + fixed: crashes in winamp 5.57 when playing tracks that have "genre" tag + + + ---------------------------------- + Release 4.60.1 - November 29, 2009 + ---------------------------------- + + WavPack Library Source Code - 4.60.1 + ------------------------------------ + fixed: filename specs in tag extractions failed in batch operations + fixed: prevent creation of APEv2 tags > 1 MB (which we can't read) + fixed: crash when decoding old WavPack files (pre version 4.0) + added: man pages to build system and updated with newer options + added: versioning info to Windows DLL + improved: build compatibility (eliminated uchar, ushort types) + + wavpack.exe (command-line encoder) - 4.60.1 + ------------------------------------------- + fixed: don't allow user to attempt to place over 1 MB into APEv2 tags + + in_wv.dll (winamp plugin) - 2.7 + ------------------------------- + added: read-only support for displaying cover art (thanks Benski!) + + wvunpack.exe (command-line decoder) - 4.60.1 + wvgain.exe (command-line ReplayGain scanner) - 4.60.1 + cool_wv4.flt (CoolEdit / Audition filter) - 2.11 + ----------------------------------------------------- + (see library changes) + + + --------------------------------- + Release 4.60 - September 27, 2009 + --------------------------------- + + WavPack Library Source Code - 4.60 + ---------------------------------- + added: API for reading & writing binary fields in APEv2 tags + fixed: recognize APEv2 tags with footers but no headers + fixed: playback of files with 8 streams (15-16 channels) + fixed: playback and seeking failed on certain rare correction files + fixed: handle case where library makes RIFF header but app adds RIFF trailer + improved: channel count limit now virtually unlimited (tested to 256) + improved: move all tag functions into new module (tags.c) + + wavpack.exe (command-line encoder) - 4.60 + ----------------------------------------- + added: --write-binary-tag command for embedded cover art + added: --no-utf8-convert command to skip Unicode character conversions + added: --raw-pcm command to specify raw PCM data (samplerate, bitdepth, num chans) + added: --channel-order accepts "..." to specify unassigned channels + added: --pair-unassigned-chans command to put unassigned channels into stereo pairs + + wvunpack.exe (command-line decoder) - 4.60 + ------------------------------------------ + added: -x (and -xx) commands for extracting arbitrary tag fields to stdout (and files) + added: --no-utf8-convert command to skip Unicode character conversions + changed: -ss command no longer dumps multiline tags (use -x instead) + improved: formatting of -ss command, also shows information on binary tags + + wvgain.exe (command-line ReplayGain scanner) - 4.60 + --------------------------------------------------- + added: -n option for processing new files only (those without ReplayGain info) + improved: increase maximum gain value generated from +24 to +64 dB + + in_wv.dll (winamp plugin) - 2.6 + cool_wv4.flt (CoolEdit / Audition filter) - 2.10 + ------------------------------------------------ + (see library changes) + + + ------------------------- + Update - January 23, 2009 + ------------------------- + + in_wv.dll (winamp plugin) - 2.6b + -------------------------------- + added: "lossless" and "category" to metadata keywords that we handle in winamp plugin + added: internationalization support to facilitate inclusion in Winamp Essentials Pack + + + ----------------------------- + Release 4.50.1 - July 3, 2008 + ----------------------------- + + WavPack Library Source Code - 4.50.1 + ------------------------------------ + fixed: alignment fault when manipulating APEv2 tags (non-x86 only) + fixed: build on UNIX via elimination of non-standard strnlen() + + wavpack.exe (command-line encoder) - 4.50.1 + wvunpack.exe (command-line decoder) - 4.50.1 + -------------------------------------------- + fixed: checking return value of iconv_open() prevents core dump on Solaris + + + ---------------------------- + Release 4.50 - June 13, 2008 + ---------------------------- + + WavPack Library Source Code - 4.50 + ---------------------------------- + added: dynamic noise shaping for improved hybrid quality + added: option to merge blocks of similar redundancy + added: ability to store and retrieve extra mode level + fixed: alignment fault on some big-endian machines + fixed: compiling with enable-mmx on gcc 4.3.x (thanks Joachim) + improved: allow bitrate to be calculated for files down to 1/10 second + improved: decoding of corrupt files (prevents heap overrun crashes) + + wavpack.exe (command-line encoder) - 4.50 + ----------------------------------------- + added: dynamic noise shaping for improved hybrid quality + added: --channel-order option to reorder nonconforming multichannel files + added: --merge-blocks option to optimize storage of LossyWAV output files + added: ignore -o on Windows for compatibility with Linux version + fixed: alignment fault on some big-endian machines + improved: reformatted and expanded --help display + + wvunpack.exe (command-line decoder) - 4.50 + ------------------------------------------ + fixed: don't ignore fractions of seconds in --skip option + added: show extra level and dns status for newer files (-s command) + added: ignore -o on Windows for compatibility with Linux version + improved: decoding of corrupt files (prevents heap overrun crashes) + improved: display bitrate for files down to 1/10 second + + in_wv.dll (winamp plugin) - 2.5 + ------------------------------- + added: transcoding API (allows CD burning, format conversion, ReplayGain calc, etc.) + added: metadata writing API (for Auto-Tag, etc.) + added: full Unicode support for info box (older Winamps) and media library + added: standard Winamp metadata display & edit for newer Winamps + added: option to pass multichannel audio + added: option to pass all audio as 16-bit (for better compatibility) + added: option to output 24-bit audio when ReplayGain is active + added: genre display to info box (older Winamps) + fixed: seek bar sometimes vacillates when moved + fixed: crash when winamp is opened with files in playlist moved or deleted + improved: hi-res audio now output as 24-bit (not 32-bit) for better compatibility (EQ, etc.) + improved: performance of adding tracks to library, especially from network drives + improved: decoding of corrupt files (prevents heap overrun crashes) + + cool_wv4.flt (CoolEdit / Audition filter) - 2.9 + ----------------------------------------------- + added: about box + added: dynamic noise shaping for improved hybrid quality + improved: display bitrate for files as short as 1/10 second + improved: decoding of corrupt files (prevents heap overrun crashes) + improved: replace "extra processing" switch with a slider (0-6) + + + -------------------------- + Release 4.41 - May 6, 2007 + -------------------------- + + WavPack Library Source Code - 4.41 + ---------------------------------- + added: create wavpackdll.dll for Windows (not used yet) + fixed: corrupt floating-point audio on big-endian machines + fixed: put MSVC projects in their own subdir (fixed build problems) + fixed: limit RIFF data buffering to 16 MB to prevent out-of-memory crash + improved: attempt to mute errors when decoding corrupt legacy WavPack files + improved: overall performance enhancements of 10% to 30% (depending on mode) + added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to + Joachim Henke) + + wavpack.exe (command-line encoder) - 4.41 + ----------------------------------------- + fixed: corrupt floating-point audio on big-endian machines + improved: refuse to encode WAV files over 4 GB or with over 16 MB RIFF data + improved: overall performance enhancements of 10% to 30% (depending on mode) + added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to + Joachim Henke) + + wvunpack.exe (command-line decoder) - 4.41 + ------------------------------------------ + fixed: corrupt floating-point audio on big-endian machines + fixed: restore files mistakenly encoded with huge RIFF chunks + improved: attempt to mute errors when decoding corrupt legacy WavPack files + improved: overall performance enhancements of 10% to 30% (depending on mode) + added: --skip and --until commands to unpack specified range of audio data + added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to + Joachim Henke) + + wvgain.exe (command-line ReplayGain scanner) - 4.41 + --------------------------------------------------- + improved: overall performance enhancements of 10% to 30% (depending on mode) + added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to + Joachim Henke) + + cool_wv4.flt (CoolEdit / Audition filter) - 2.8 + ----------------------------------------------- + fixed: read all RIFF metadata from files created in other applications + improved: attempt to mute errors when decoding corrupt legacy WavPack files + improved: overall performance enhancements of 10% to 30% (depending on mode) + added: MMX intrinsics for 24-bit (and higher) stereo encoding (thanks to + Joachim Henke) + + + ------------------------------- + Release 4.40 - December 3, 2006 + ------------------------------- + + WavPack Library Source Code - 4.40 + ---------------------------------- + added: new hardware-friendly "high" mode that compresses almost as well as + old "high" mode but decodes significantly faster; old "high" mode + now available as "very high" + added: option added to improve compression of mono material in stereo files + (requires at least version 4.3 decoder) + added: function to obtain channel mapping information on decoding + added: function to get trailing wrapper info (RIFF) without decoding file + improved: "extra" mode levels 1-3 completely revamped, fast enough for use + improved: reorganized to create a standard library that should more easily + integrate into other applications; eliminated namespace issues + improved: more robust handling of corrupt files + + wavpack.exe (command-line encoder) - 4.40 + ----------------------------------------- + added: accepts long option names including --help for full usage info + added: new hardware-friendly "high" mode that compresses almost as well as + old "high" mode but decodes significantly faster; old "high" mode + now available as "very high" (-hh) + added: --optimize-mono option added to improve compression of mono material + in stereo files (requires at least version 4.3 decoder) + improved: "extra" mode levels 1-3 completely revamped, fast enough for use + improved: switched to Microsoft Visual Studio 2005 (win32 only) + removed: support for Windows 95 + + wvunpack.exe (command-line decoder) - 4.40 + ------------------------------------------ + added: cuesheet extraction (to .cue file or stdout) + added: wav header generation on decode for files with missing RIFF + information, or forced with -w option + added: more summary info (wrapper info + channel assignments) + improved: more robust handling of corrupt files + improved: separate options for raw (-r) and blind stream decoding (-b) + improved: switched to Microsoft Visual Studio 2005 (win32 only) + removed: support for Windows 95 + + wvgain.exe (command-line ReplayGain scanner) - 4.40 + --------------------------------------------------- + improved: switched to Microsoft Visual Studio 2005 (win32 only) + removed: support for Windows 95 + + wvselfx.exe (self-extraction stub) - 4.40 + ------------------------------------------ + added: automatic cuesheet extraction (if present in APEv2 tag) + + in_wv.dll (winamp plugin) - 2.4 + ------------------------------- + fixed: quietly skips deleted files in playlist + improved: more robust handling of corrupt files + improved: APEv2 tags are read even if followed by ID3v1 tag + + cool_wv4.flt (CoolEdit / Audition filter) - 2.7 + ----------------------------------------------- + added: new hardware-friendly "high" mode that compresses almost as well as + old "high" mode but decodes significantly faster; old "high" mode + now available as "v. high" + improved: more robust handling of corrupt files + + ---------------------- Update - April 5, 2006 ---------------------- WavPack Library Source Code - 4.32 + wavpack.exe (command-line encoder) - 4.32 ----------------------------------------- fixed: generating RIFF headers on big-endian machines caused crash diff --git a/Frameworks/WavPack/Files/Makefile.am b/Frameworks/WavPack/Files/Makefile.am deleted file mode 100644 index fc1549260..000000000 --- a/Frameworks/WavPack/Files/Makefile.am +++ /dev/null @@ -1,32 +0,0 @@ -AUTOMAKE_OPTIONS = foreign -bin_PROGRAMS = wavpack wvunpack wvgain - -lib_LTLIBRARIES = libwavpack.la - -wpincludedir = $(prefix)/include/wavpack - -wpinclude_HEADERS = md5.h wavpack.h wputils.h unpack3.h - -libwavpack_la_SOURCES = bits.c float.c metadata.c unpack.c unpack3.c \ - wputils.c words.c md5.c extra1.c extra2.c pack.c \ - md5.h wavpack.h wputils.h unpack3.h -libwavpack_la_CFLAGS = -DPACK -DUNPACK -DUSE_FSTREAMS -DTAGS -DSEEKING -DVER3 -libwavpack_la_LDFLAGS = -lm @ICONV_LIBS@ - -wavpack_SOURCES = wavpack.c utils.c -wavpack_CFLAGS = -DPACK -wavpack_LDFLAGS = -lm -wavpack_LDADD = libwavpack.la - -wvunpack_SOURCES = wvunpack.c utils.c -wvunpack_CFLAGS = -DUNPACK -DUSE_FSTREAMS -wvunpack_LDFLAGS = -lm -wvunpack_LDADD = libwavpack.la - -wvgain_SOURCES = wvgain.c utils.c -wvgain_CFLAGS = -DUNPACK -DUSE_FSTREAMS -wvgain_LDFLAGS = -lm -wvgain_LDADD = libwavpack.la - -pkgconfigdir = $(libdir)/pkgconfig -pkgconfig_DATA = wavpack.pc diff --git a/Frameworks/WavPack/Files/README b/Frameworks/WavPack/Files/README index fd8fe6f6b..5c7c76b08 100644 --- a/Frameworks/WavPack/Files/README +++ b/Frameworks/WavPack/Files/README @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////////////////////// // **** WAVPACK **** // // Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2006 Conifer Software. // +// Copyright (c) 1998 - 2013 Conifer Software. // // All Rights Reserved. // // Distributed under the BSD Software License (see license.txt) // //////////////////////////////////////////////////////////////////////////// @@ -10,14 +10,15 @@ This package contains all the source code required to build the WavPack command-line programs and the WavPack library and it has been tested on many platforms. -On Windows there are solution and project files for Visual Studio 2005 and +On Windows there are solution and project files for Visual Studio 2008 and additional sourcecode to build the CoolEdit/Audition plugin and the winamp plugin. The CoolEdit/Audition plugin provides a good example for using the -library to both read and write WavPack files. +library to both read and write WavPack files. Both 32-bit and 64-bit +platforms are provided. To build everything on Linux, type: -1. ./configure [--enable-mmx] +1. ./configure [--enable-mmx] [--enable-man] 2. make 3. make install (optionally, to install into /usr/local/bin) diff --git a/Frameworks/WavPack/Files/autogen.sh b/Frameworks/WavPack/Files/autogen.sh deleted file mode 100755 index 39b82fcd9..000000000 --- a/Frameworks/WavPack/Files/autogen.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -touch NEWS README AUTHORS ChangeLog -aclocal -libtoolize --copy -automake --add-missing -autoconf diff --git a/Frameworks/WavPack/Files/configure.ac b/Frameworks/WavPack/Files/configure.ac deleted file mode 100644 index 2bc54a63f..000000000 --- a/Frameworks/WavPack/Files/configure.ac +++ /dev/null @@ -1,135 +0,0 @@ -# wavpack 4.60.1 configure.ac - -AC_INIT(wavpack, 4.60.1, bryant@wavpack.com) -AM_INIT_AUTOMAKE(wavpack, 4.60.1, bryant@wavpack.com) -AC_CONFIG_SRCDIR([src/pack.c]) -AM_MAINTAINER_MODE - -LIBWAVPACK_MAJOR=4 -LIBWAVPACK_MINOR=60 -LIBWAVPACK_MICRO=1 -LIBWAVPACK_VERSION_STRING=$LIBWAVPACK_MAJOR.$LIBWAVPACK_MINOR.$LIBWAVPACK_MICRO - -AC_DEFINE_UNQUOTED(LIBWAVPACK_MAJOR, $LIBWAVPACK_MAJOR, [libwavpack major version]) -AC_DEFINE_UNQUOTED(LIBWAVPACK_MINOR, $LIBWAVPACK_MINOR, [libwavpack minor version]) -AC_DEFINE_UNQUOTED(LIBWAVPACK_MICRO, $LIBWAVPACK_MICRO, [libwavpack micro version]) -AC_DEFINE_UNQUOTED(LIBWAVPACK_VERSION_STRING, "$LIBWAVPACK_VERSION_STRING", [libwavpack version string]) - -# set libtool versioning -# +1 : 0 : +1 == new interface that does not break old one. -# +1 : 0 : 0 == changed/removed an interface. Breaks old apps. -# ? : +1 : ? == internal changes that doesn't break anything. -# CURRENT : REVISION : AGE -LT_CURRENT=2 -LT_REVISION=4 -LT_AGE=1 - -AC_SUBST(LT_CURRENT) -AC_SUBST(LT_REVISION) -AC_SUBST(LT_AGE) - -# Check for os version -VERSION_OS=$(uname -s) -AC_DEFINE_UNQUOTED(VERSION_OS, "$VERSION_OS", [os version]) - -# Check for processor characteristics -AC_C_BIGENDIAN(AC_DEFINE([HIGHFIRST], [1], [big-endian machine])) - -# Checks for programs. -AC_PROG_CC -AC_LIBTOOL_WIN32_DLL -AC_PROG_LIBTOOL -AC_PROG_INSTALL -AM_PROG_CC_C_O - -AC_HEADER_STDC - -# Checks for libraries. -AC_CHECK_LIBM -AC_SUBST(LIBM) - -# Check if cross-compiling on mingw -AC_MINGW32 - -if test "x$MINGW32" != "xyes" ; then -# Check for iconv -AC_ARG_WITH(iconv, [[ --with-iconv[=DIR] add ICONV support [yes]]]) -if test "$with_iconv" = "no" ; then - AC_MSG_ERROR([[Sorry, you can't deactivate iconv.]]) -else - if test "$with_iconv" != "yes" -a "$with_iconv" != "" ; then - ICONV_CFLAGS="${CPPFLAGS} -I$with_iconv/include" - ICONV_LIBS="-L$with_iconv/lib" - fi - - AC_CHECK_HEADER(iconv.h, - AC_MSG_CHECKING(for iconv) - AC_TRY_LINK([#include -#include ],[ -iconv_t cd = iconv_open ("",""); -iconv (cd, NULL, NULL, NULL, NULL);],[ - AC_MSG_RESULT(yes) - WITH_ICONV=1],[ - AC_MSG_RESULT(no) - AC_MSG_CHECKING(for iconv in -liconv) - - old_ldflags="${LDFLAGS}" - old_libs="${LIBS}" - LDFLAGS="${LDFLAGS} ${ICONV_LIBS}" - LIBS="${LIBS} -liconv" - - AC_TRY_LINK([#include -#include ],[ -iconv_t cd = iconv_open ("",""); -iconv (cd, NULL, NULL, NULL, NULL);],[ - AC_MSG_RESULT(yes) - WITH_ICONV=1 - ICONV_LIBS="${ICONV_LIBS} -liconv" - ICONV="-liconv"],[ - AC_MSG_ERROR([[Can't find iconv libraries.]])]) - LDFLAGS=$old_ldflags - LIBS=$old_libs - ]), - AC_MSG_ERROR([[Can't find iconv headers.]])) -fi -AC_SUBST(ICONV_LIBS) -AC_SUBST(ICONV) -fi - -AC_ARG_ENABLE(mmx, [[ --enable-mmx enable MMX optimizations [default=no]]]) -if test "x$enable_mmx" = "xyes" ; then - AC_DEFINE([OPT_MMX], 1, [MMX optimization]) - $CC $CFLAGS -mmmx -S -o /dev/null -xc /dev/null > /dev/null 2>&1 && CFLAGS="-mmmx $CFLAGS" -fi - -AC_ARG_ENABLE(man, - [AC_HELP_STRING([--enable-man], - [regenerate man pages from Docbook [default=no]])],enable_man=yes, - enable_man=no) - -if test "${enable_man}" != no; then - dnl - dnl Check for xsltproc - dnl - AC_PATH_PROG([XSLTPROC], [xsltproc]) - if test -z "$XSLTPROC"; then - enable_man=no - fi - - dnl check for DocBook DTD and stylesheets in the local catalog. - JH_CHECK_XML_CATALOG([-//OASIS//DTD DocBook XML V4.1.2//EN], - [DocBook XML DTD V4.1.2],,enable_man=no) - JH_CHECK_XML_CATALOG([http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl], - [DocBook XSL Stylesheets],,enable_man=no) -fi - -AM_CONDITIONAL(ENABLE_MAN, test x$enable_man != xno) - -AC_CONFIG_FILES( -Makefile -wavpack.pc -src/Makefile -include/Makefile -cli/Makefile -man/Makefile) -AC_OUTPUT diff --git a/Frameworks/WavPack/Files/depcomp b/Frameworks/WavPack/Files/depcomp deleted file mode 100755 index e5f9736c7..000000000 --- a/Frameworks/WavPack/Files/depcomp +++ /dev/null @@ -1,589 +0,0 @@ -#! /bin/sh -# depcomp - compile a program generating dependencies as side-effects - -scriptversion=2007-03-29.01 - -# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software -# Foundation, Inc. - -# 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, 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. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -# Originally written by Alexandre Oliva . - -case $1 in - '') - echo "$0: No command. Try \`$0 --help' for more information." 1>&2 - exit 1; - ;; - -h | --h*) - cat <<\EOF -Usage: depcomp [--help] [--version] PROGRAM [ARGS] - -Run PROGRAMS ARGS to compile a file, generating dependencies -as side-effects. - -Environment variables: - depmode Dependency tracking mode. - source Source file read by `PROGRAMS ARGS'. - object Object file output by `PROGRAMS ARGS'. - DEPDIR directory where to store dependencies. - depfile Dependency file to output. - tmpdepfile Temporary file to use when outputing dependencies. - libtool Whether libtool is used (yes/no). - -Report bugs to . -EOF - exit $? - ;; - -v | --v*) - echo "depcomp $scriptversion" - exit $? - ;; -esac - -if test -z "$depmode" || test -z "$source" || test -z "$object"; then - echo "depcomp: Variables source, object and depmode must be set" 1>&2 - exit 1 -fi - -# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po. -depfile=${depfile-`echo "$object" | - sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`} -tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} - -rm -f "$tmpdepfile" - -# Some modes work just like other modes, but use different flags. We -# parameterize here, but still list the modes in the big case below, -# to make depend.m4 easier to write. Note that we *cannot* use a case -# here, because this file can only contain one case statement. -if test "$depmode" = hp; then - # HP compiler uses -M and no extra arg. - gccflag=-M - depmode=gcc -fi - -if test "$depmode" = dashXmstdout; then - # This is just like dashmstdout with a different argument. - dashmflag=-xM - depmode=dashmstdout -fi - -case "$depmode" in -gcc3) -## gcc 3 implements dependency tracking that does exactly what -## we want. Yay! Note: for some reason libtool 1.4 doesn't like -## it if -MD -MP comes after the -MF stuff. Hmm. -## Unfortunately, FreeBSD c89 acceptance of flags depends upon -## the command line argument order; so add the flags where they -## appear in depend2.am. Note that the slowdown incurred here -## affects only configure: in makefiles, %FASTDEP% shortcuts this. - for arg - do - case $arg in - -c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;; - *) set fnord "$@" "$arg" ;; - esac - shift # fnord - shift # $arg - done - "$@" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - mv "$tmpdepfile" "$depfile" - ;; - -gcc) -## There are various ways to get dependency output from gcc. Here's -## why we pick this rather obscure method: -## - Don't want to use -MD because we'd like the dependencies to end -## up in a subdir. Having to rename by hand is ugly. -## (We might end up doing this anyway to support other compilers.) -## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like -## -MM, not -M (despite what the docs say). -## - Using -M directly means running the compiler twice (even worse -## than renaming). - if test -z "$gccflag"; then - gccflag=-MD, - fi - "$@" -Wp,"$gccflag$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - echo "$object : \\" > "$depfile" - alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz -## The second -e expression handles DOS-style file names with drive letters. - sed -e 's/^[^:]*: / /' \ - -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" -## This next piece of magic avoids the `deleted header file' problem. -## The problem is that when a header file which appears in a .P file -## is deleted, the dependency causes make to die (because there is -## typically no way to rebuild the header). We avoid this by adding -## dummy dependencies for each header file. Too bad gcc doesn't do -## this for us directly. - tr ' ' ' -' < "$tmpdepfile" | -## Some versions of gcc put a space before the `:'. On the theory -## that the space means something, we add a space to the output as -## well. -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp) - # This case exists only to let depend.m4 do its work. It works by - # looking at the text of this script. This case will never be run, - # since it is checked for above. - exit 1 - ;; - -sgi) - if test "$libtool" = yes; then - "$@" "-Wp,-MDupdate,$tmpdepfile" - else - "$@" -MDupdate "$tmpdepfile" - fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - - if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files - echo "$object : \\" > "$depfile" - - # Clip off the initial element (the dependent). Don't try to be - # clever and replace this with sed code, as IRIX sed won't handle - # lines with more than a fixed number of characters (4096 in - # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; - # the IRIX cc adds comments like `#:fec' to the end of the - # dependency line. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ - tr ' -' ' ' >> $depfile - echo >> $depfile - - # The second pass generates a dummy entry for each header file. - tr ' ' ' -' < "$tmpdepfile" \ - | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ - >> $depfile - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -aix) - # The C for AIX Compiler uses -M and outputs the dependencies - # in a .u file. In older versions, this file always lives in the - # current directory. Also, the AIX compiler puts `$object:' at the - # start of each line; $object doesn't have directory information. - # Version 6 uses the directory in both cases. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.u - tmpdepfile2=$base.u - tmpdepfile3=$dir.libs/$base.u - "$@" -Wc,-M - else - tmpdepfile1=$dir$base.u - tmpdepfile2=$dir$base.u - tmpdepfile3=$dir$base.u - "$@" -M - fi - stat=$? - - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - # Each line is of the form `foo.o: dependent.h'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a tab and a space in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" - else - # The sourcefile does not contain any dependencies, so just - # store a dummy comment line, to avoid errors with the Makefile - # "include basename.Plo" scheme. - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -icc) - # Intel's C compiler understands `-MD -MF file'. However on - # icc -MD -MF foo.d -c -o sub/foo.o sub/foo.c - # ICC 7.0 will fill foo.d with something like - # foo.o: sub/foo.c - # foo.o: sub/foo.h - # which is wrong. We want: - # sub/foo.o: sub/foo.c - # sub/foo.o: sub/foo.h - # sub/foo.c: - # sub/foo.h: - # ICC 7.1 will output - # foo.o: sub/foo.c sub/foo.h - # and will wrap long lines using \ : - # foo.o: sub/foo.c ... \ - # sub/foo.h ... \ - # ... - - "$@" -MD -MF "$tmpdepfile" - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile" - exit $stat - fi - rm -f "$depfile" - # Each line is of the form `foo.o: dependent.h', - # or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'. - # Do two passes, one to just change these to - # `$object: dependent.h' and one to simply `dependent.h:'. - sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile" - # Some versions of the HPUX 10.20 sed can't process this invocation - # correctly. Breaking it into two sed invocations is a workaround. - sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" | - sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -hp2) - # The "hp" stanza above does not work with aCC (C++) and HP's ia64 - # compilers, which have integrated preprocessors. The correct option - # to use with these is +Maked; it writes dependencies to a file named - # 'foo.d', which lands next to the object file, wherever that - # happens to be. - # Much of this is similar to the tru64 case; see comments there. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - if test "$libtool" = yes; then - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir.libs/$base.d - "$@" -Wc,+Maked - else - tmpdepfile1=$dir$base.d - tmpdepfile2=$dir$base.d - "$@" +Maked - fi - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," "$tmpdepfile" > "$depfile" - # Add `dependent.h:' lines. - sed -ne '2,${; s/^ *//; s/ \\*$//; s/$/:/; p;}' "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" "$tmpdepfile2" - ;; - -tru64) - # The Tru64 compiler uses -MD to generate dependencies as a side - # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. - # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put - # dependencies in `foo.d' instead, so we check for that too. - # Subdirectories are respected. - dir=`echo "$object" | sed -e 's|/[^/]*$|/|'` - test "x$dir" = "x$object" && dir= - base=`echo "$object" | sed -e 's|^.*/||' -e 's/\.o$//' -e 's/\.lo$//'` - - if test "$libtool" = yes; then - # With Tru64 cc, shared objects can also be used to make a - # static library. This mechanism is used in libtool 1.4 series to - # handle both shared and static libraries in a single compilation. - # With libtool 1.4, dependencies were output in $dir.libs/$base.lo.d. - # - # With libtool 1.5 this exception was removed, and libtool now - # generates 2 separate objects for the 2 libraries. These two - # compilations output dependencies in $dir.libs/$base.o.d and - # in $dir$base.o.d. We have to check for both files, because - # one of the two compilations can be disabled. We should prefer - # $dir$base.o.d over $dir.libs/$base.o.d because the latter is - # automatically cleaned when .libs/ is deleted, while ignoring - # the former would cause a distcleancheck panic. - tmpdepfile1=$dir.libs/$base.lo.d # libtool 1.4 - tmpdepfile2=$dir$base.o.d # libtool 1.5 - tmpdepfile3=$dir.libs/$base.o.d # libtool 1.5 - tmpdepfile4=$dir.libs/$base.d # Compaq CCC V6.2-504 - "$@" -Wc,-MD - else - tmpdepfile1=$dir$base.o.d - tmpdepfile2=$dir$base.d - tmpdepfile3=$dir$base.d - tmpdepfile4=$dir$base.d - "$@" -MD - fi - - stat=$? - if test $stat -eq 0; then : - else - rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" - exit $stat - fi - - for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3" "$tmpdepfile4" - do - test -f "$tmpdepfile" && break - done - if test -f "$tmpdepfile"; then - sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" - # That's a tab and a space in the []. - sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" - else - echo "#dummy" > "$depfile" - fi - rm -f "$tmpdepfile" - ;; - -#nosideeffect) - # This comment above is used by automake to tell side-effect - # dependency tracking mechanisms from slower ones. - -dashmstdout) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout, regardless of -o. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - - # Remove `-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - test -z "$dashmflag" && dashmflag=-M - # Require at least two characters before searching for `:' - # in the target name. This is to cope with DOS-style filenames: - # a dependency such as `c:/foo/bar' could be seen as target `c' otherwise. - "$@" $dashmflag | - sed 's:^[ ]*[^: ][^:][^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - tr ' ' ' -' < "$tmpdepfile" | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -dashXmstdout) - # This case only exists to satisfy depend.m4. It is never actually - # run, as this mode is specially recognized in the preamble. - exit 1 - ;; - -makedepend) - "$@" || exit $? - # Remove any Libtool call - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - # X makedepend - shift - cleared=no - for arg in "$@"; do - case $cleared in - no) - set ""; shift - cleared=yes ;; - esac - case "$arg" in - -D*|-I*) - set fnord "$@" "$arg"; shift ;; - # Strip any option that makedepend may not understand. Remove - # the object too, otherwise makedepend will parse it as a source file. - -*|$object) - ;; - *) - set fnord "$@" "$arg"; shift ;; - esac - done - obj_suffix="`echo $object | sed 's/^.*\././'`" - touch "$tmpdepfile" - ${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@" - rm -f "$depfile" - cat < "$tmpdepfile" > "$depfile" - sed '1,2d' "$tmpdepfile" | tr ' ' ' -' | \ -## Some versions of the HPUX 10.20 sed can't process this invocation -## correctly. Breaking it into two sed invocations is a workaround. - sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" "$tmpdepfile".bak - ;; - -cpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout. - "$@" || exit $? - - # Remove the call to Libtool. - if test "$libtool" = yes; then - while test $1 != '--mode=compile'; do - shift - done - shift - fi - - # Remove `-o $object'. - IFS=" " - for arg - do - case $arg in - -o) - shift - ;; - $object) - shift - ;; - *) - set fnord "$@" "$arg" - shift # fnord - shift # $arg - ;; - esac - done - - "$@" -E | - sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \ - -e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | - sed '$ s: \\$::' > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - cat < "$tmpdepfile" >> "$depfile" - sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -msvisualcpp) - # Important note: in order to support this mode, a compiler *must* - # always write the preprocessed file to stdout, regardless of -o, - # because we must use -o when running libtool. - "$@" || exit $? - IFS=" " - for arg - do - case "$arg" in - "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") - set fnord "$@" - shift - shift - ;; - *) - set fnord "$@" "$arg" - shift - shift - ;; - esac - done - "$@" -E | - sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" - rm -f "$depfile" - echo "$object : \\" > "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" - echo " " >> "$depfile" - . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" - rm -f "$tmpdepfile" - ;; - -none) - exec "$@" - ;; - -*) - echo "Unknown depmode $depmode" 1>&2 - exit 1 - ;; -esac - -exit 0 - -# Local Variables: -# mode: shell-script -# sh-indentation: 2 -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/Frameworks/WavPack/Files/install-sh b/Frameworks/WavPack/Files/install-sh deleted file mode 100755 index 1a8353401..000000000 --- a/Frameworks/WavPack/Files/install-sh +++ /dev/null @@ -1,323 +0,0 @@ -#!/bin/sh -# install - install a program, script, or datafile - -scriptversion=2005-02-02.21 - -# This originates from X11R5 (mit/util/scripts/install.sh), which was -# later released in X11R6 (xc/config/util/install.sh) with the -# following copyright and license. -# -# Copyright (C) 1994 X Consortium -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC- -# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -# -# Except as contained in this notice, the name of the X Consortium shall not -# be used in advertising or otherwise to promote the sale, use or other deal- -# ings in this Software without prior written authorization from the X Consor- -# tium. -# -# -# FSF changes to this file are in the public domain. -# -# Calling this script install-sh is preferred over install.sh, to prevent -# `make' implicit rules from creating a file called install from it -# when there is no Makefile. -# -# This script is compatible with the BSD install script, but was written -# from scratch. It can only install one file at a time, a restriction -# shared with many OS's install programs. - -# set DOITPROG to echo to test this script - -# Don't use :- since 4.3BSD and earlier shells don't like it. -doit="${DOITPROG-}" - -# put in absolute paths if you don't have them in your path; or use env. vars. - -mvprog="${MVPROG-mv}" -cpprog="${CPPROG-cp}" -chmodprog="${CHMODPROG-chmod}" -chownprog="${CHOWNPROG-chown}" -chgrpprog="${CHGRPPROG-chgrp}" -stripprog="${STRIPPROG-strip}" -rmprog="${RMPROG-rm}" -mkdirprog="${MKDIRPROG-mkdir}" - -chmodcmd="$chmodprog 0755" -chowncmd= -chgrpcmd= -stripcmd= -rmcmd="$rmprog -f" -mvcmd="$mvprog" -src= -dst= -dir_arg= -dstarg= -no_target_directory= - -usage="Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE - or: $0 [OPTION]... SRCFILES... DIRECTORY - or: $0 [OPTION]... -t DIRECTORY SRCFILES... - or: $0 [OPTION]... -d DIRECTORIES... - -In the 1st form, copy SRCFILE to DSTFILE. -In the 2nd and 3rd, copy all SRCFILES to DIRECTORY. -In the 4th, create DIRECTORIES. - -Options: --c (ignored) --d create directories instead of installing files. --g GROUP $chgrpprog installed files to GROUP. --m MODE $chmodprog installed files to MODE. --o USER $chownprog installed files to USER. --s $stripprog installed files. --t DIRECTORY install into DIRECTORY. --T report an error if DSTFILE is a directory. ---help display this help and exit. ---version display version info and exit. - -Environment variables override the default commands: - CHGRPPROG CHMODPROG CHOWNPROG CPPROG MKDIRPROG MVPROG RMPROG STRIPPROG -" - -while test -n "$1"; do - case $1 in - -c) shift - continue;; - - -d) dir_arg=true - shift - continue;; - - -g) chgrpcmd="$chgrpprog $2" - shift - shift - continue;; - - --help) echo "$usage"; exit $?;; - - -m) chmodcmd="$chmodprog $2" - shift - shift - continue;; - - -o) chowncmd="$chownprog $2" - shift - shift - continue;; - - -s) stripcmd=$stripprog - shift - continue;; - - -t) dstarg=$2 - shift - shift - continue;; - - -T) no_target_directory=true - shift - continue;; - - --version) echo "$0 $scriptversion"; exit $?;; - - *) # When -d is used, all remaining arguments are directories to create. - # When -t is used, the destination is already specified. - test -n "$dir_arg$dstarg" && break - # Otherwise, the last argument is the destination. Remove it from $@. - for arg - do - if test -n "$dstarg"; then - # $@ is not empty: it contains at least $arg. - set fnord "$@" "$dstarg" - shift # fnord - fi - shift # arg - dstarg=$arg - done - break;; - esac -done - -if test -z "$1"; then - if test -z "$dir_arg"; then - echo "$0: no input file specified." >&2 - exit 1 - fi - # It's OK to call `install-sh -d' without argument. - # This can happen when creating conditional directories. - exit 0 -fi - -for src -do - # Protect names starting with `-'. - case $src in - -*) src=./$src ;; - esac - - if test -n "$dir_arg"; then - dst=$src - src= - - if test -d "$dst"; then - mkdircmd=: - chmodcmd= - else - mkdircmd=$mkdirprog - fi - else - # Waiting for this to be detected by the "$cpprog $src $dsttmp" command - # might cause directories to be created, which would be especially bad - # if $src (and thus $dsttmp) contains '*'. - if test ! -f "$src" && test ! -d "$src"; then - echo "$0: $src does not exist." >&2 - exit 1 - fi - - if test -z "$dstarg"; then - echo "$0: no destination specified." >&2 - exit 1 - fi - - dst=$dstarg - # Protect names starting with `-'. - case $dst in - -*) dst=./$dst ;; - esac - - # If destination is a directory, append the input filename; won't work - # if double slashes aren't ignored. - if test -d "$dst"; then - if test -n "$no_target_directory"; then - echo "$0: $dstarg: Is a directory" >&2 - exit 1 - fi - dst=$dst/`basename "$src"` - fi - fi - - # This sed command emulates the dirname command. - dstdir=`echo "$dst" | sed -e 's,/*$,,;s,[^/]*$,,;s,/*$,,;s,^$,.,'` - - # Make sure that the destination directory exists. - - # Skip lots of stat calls in the usual case. - if test ! -d "$dstdir"; then - defaultIFS=' - ' - IFS="${IFS-$defaultIFS}" - - oIFS=$IFS - # Some sh's can't handle IFS=/ for some reason. - IFS='%' - set x `echo "$dstdir" | sed -e 's@/@%@g' -e 's@^%@/@'` - shift - IFS=$oIFS - - pathcomp= - - while test $# -ne 0 ; do - pathcomp=$pathcomp$1 - shift - if test ! -d "$pathcomp"; then - $mkdirprog "$pathcomp" - # mkdir can fail with a `File exist' error in case several - # install-sh are creating the directory concurrently. This - # is OK. - test -d "$pathcomp" || exit - fi - pathcomp=$pathcomp/ - done - fi - - if test -n "$dir_arg"; then - $doit $mkdircmd "$dst" \ - && { test -z "$chowncmd" || $doit $chowncmd "$dst"; } \ - && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } \ - && { test -z "$stripcmd" || $doit $stripcmd "$dst"; } \ - && { test -z "$chmodcmd" || $doit $chmodcmd "$dst"; } - - else - dstfile=`basename "$dst"` - - # Make a couple of temp file names in the proper directory. - dsttmp=$dstdir/_inst.$$_ - rmtmp=$dstdir/_rm.$$_ - - # Trap to clean up those temp files at exit. - trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0 - trap '(exit $?); exit' 1 2 13 15 - - # Copy the file name to the temp name. - $doit $cpprog "$src" "$dsttmp" && - - # and set any options; do chmod last to preserve setuid bits. - # - # If any of these fail, we abort the whole thing. If we want to - # ignore errors from any of these, just make sure not to ignore - # errors from the above "$doit $cpprog $src $dsttmp" command. - # - { test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } \ - && { test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } \ - && { test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } \ - && { test -z "$chmodcmd" || $doit $chmodcmd "$dsttmp"; } && - - # Now rename the file to the real destination. - { $doit $mvcmd -f "$dsttmp" "$dstdir/$dstfile" 2>/dev/null \ - || { - # The rename failed, perhaps because mv can't rename something else - # to itself, or perhaps because mv is so ancient that it does not - # support -f. - - # Now remove or move aside any old file at destination location. - # We try this two ways since rm can't unlink itself on some - # systems and the destination file might be busy for other - # reasons. In this case, the final cleanup might fail but the new - # file should still install successfully. - { - if test -f "$dstdir/$dstfile"; then - $doit $rmcmd -f "$dstdir/$dstfile" 2>/dev/null \ - || $doit $mvcmd -f "$dstdir/$dstfile" "$rmtmp" 2>/dev/null \ - || { - echo "$0: cannot unlink or rename $dstdir/$dstfile" >&2 - (exit 1); exit 1 - } - else - : - fi - } && - - # Now rename the file to the real destination. - $doit $mvcmd "$dsttmp" "$dstdir/$dstfile" - } - } - fi || { (exit 1); exit 1; } -done - -# The final little trick to "correctly" pass the exit status to the exit trap. -{ - (exit 0); exit 0 -} - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/Frameworks/WavPack/Files/license.txt b/Frameworks/WavPack/Files/license.txt index 6ffc23b93..e5e231df1 100644 --- a/Frameworks/WavPack/Files/license.txt +++ b/Frameworks/WavPack/Files/license.txt @@ -1,4 +1,4 @@ - Copyright (c) 1998 - 2009 Conifer Software + Copyright (c) 1998 - 2013 Conifer Software All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/Frameworks/WavPack/Files/md5.c b/Frameworks/WavPack/Files/md5.c index 31433f216..170024098 100644 --- a/Frameworks/WavPack/Files/md5.c +++ b/Frameworks/WavPack/Files/md5.c @@ -157,7 +157,7 @@ void MD5Final(digest, ctx) MD5Transform(ctx->buf, (uint32 *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); memcpy(digest, ctx->buf, 16); - memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ + memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */ } diff --git a/Frameworks/WavPack/Files/missing b/Frameworks/WavPack/Files/missing deleted file mode 100755 index 1c8ff7049..000000000 --- a/Frameworks/WavPack/Files/missing +++ /dev/null @@ -1,367 +0,0 @@ -#! /bin/sh -# Common stub for a few missing GNU programs while installing. - -scriptversion=2006-05-10.23 - -# Copyright (C) 1996, 1997, 1999, 2000, 2002, 2003, 2004, 2005, 2006 -# Free Software Foundation, Inc. -# Originally by Fran,cois Pinard , 1996. - -# 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, 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. - -# As a special exception to the GNU General Public License, if you -# distribute this file as part of a program that contains a -# configuration script generated by Autoconf, you may include it under -# the same distribution terms that you use for the rest of that program. - -if test $# -eq 0; then - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 -fi - -run=: -sed_output='s/.* --output[ =]\([^ ]*\).*/\1/p' -sed_minuso='s/.* -o \([^ ]*\).*/\1/p' - -# In the cases where this matters, `missing' is being run in the -# srcdir already. -if test -f configure.ac; then - configure_ac=configure.ac -else - configure_ac=configure.in -fi - -msg="missing on your system" - -case $1 in ---run) - # Try to run requested program, and just exit if it succeeds. - run= - shift - "$@" && exit 0 - # Exit code 63 means version mismatch. This often happens - # when the user try to use an ancient version of a tool on - # a file that requires a minimum version. In this case we - # we should proceed has if the program had been absent, or - # if --run hadn't been passed. - if test $? = 63; then - run=: - msg="probably too old" - fi - ;; - - -h|--h|--he|--hel|--help) - echo "\ -$0 [OPTION]... PROGRAM [ARGUMENT]... - -Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an -error status if there is no known handling for PROGRAM. - -Options: - -h, --help display this help and exit - -v, --version output version information and exit - --run try to run the given command, and emulate it if it fails - -Supported PROGRAM values: - aclocal touch file \`aclocal.m4' - autoconf touch file \`configure' - autoheader touch file \`config.h.in' - autom4te touch the output file, or create a stub one - automake touch all \`Makefile.in' files - bison create \`y.tab.[ch]', if possible, from existing .[ch] - flex create \`lex.yy.c', if possible, from existing .c - help2man touch the output file - lex create \`lex.yy.c', if possible, from existing .c - makeinfo touch the output file - tar try tar, gnutar, gtar, then tar without non-portable flags - yacc create \`y.tab.[ch]', if possible, from existing .[ch] - -Send bug reports to ." - exit $? - ;; - - -v|--v|--ve|--ver|--vers|--versi|--versio|--version) - echo "missing $scriptversion (GNU Automake)" - exit $? - ;; - - -*) - echo 1>&2 "$0: Unknown \`$1' option" - echo 1>&2 "Try \`$0 --help' for more information" - exit 1 - ;; - -esac - -# Now exit if we have it, but it failed. Also exit now if we -# don't have it and --version was passed (most likely to detect -# the program). -case $1 in - lex|yacc) - # Not GNU programs, they don't have --version. - ;; - - tar) - if test -n "$run"; then - echo 1>&2 "ERROR: \`tar' requires --run" - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - exit 1 - fi - ;; - - *) - if test -z "$run" && ($1 --version) > /dev/null 2>&1; then - # We have it, but it failed. - exit 1 - elif test "x$2" = "x--version" || test "x$2" = "x--help"; then - # Could not run --version or --help. This is probably someone - # running `$TOOL --version' or `$TOOL --help' to check whether - # $TOOL exists and not knowing $TOOL uses missing. - exit 1 - fi - ;; -esac - -# If it does not exist, or fails to run (possibly an outdated version), -# try to emulate it. -case $1 in - aclocal*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acinclude.m4' or \`${configure_ac}'. You might want - to install the \`Automake' and \`Perl' packages. Grab them from - any GNU archive site." - touch aclocal.m4 - ;; - - autoconf) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`${configure_ac}'. You might want to install the - \`Autoconf' and \`GNU m4' packages. Grab them from any GNU - archive site." - touch configure - ;; - - autoheader) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`acconfig.h' or \`${configure_ac}'. You might want - to install the \`Autoconf' and \`GNU m4' packages. Grab them - from any GNU archive site." - files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` - test -z "$files" && files="config.h" - touch_files= - for f in $files; do - case $f in - *:*) touch_files="$touch_files "`echo "$f" | - sed -e 's/^[^:]*://' -e 's/:.*//'`;; - *) touch_files="$touch_files $f.in";; - esac - done - touch $touch_files - ;; - - automake*) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. - You might want to install the \`Automake' and \`Perl' packages. - Grab them from any GNU archive site." - find . -type f -name Makefile.am -print | - sed 's/\.am$/.in/' | - while read f; do touch "$f"; done - ;; - - autom4te) - echo 1>&2 "\ -WARNING: \`$1' is needed, but is $msg. - You might have modified some files without having the - proper tools for further handling them. - You can get \`$1' as part of \`Autoconf' from any GNU - archive site." - - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo "#! /bin/sh" - echo "# Created by GNU Automake missing as a replacement of" - echo "# $ $@" - echo "exit 0" - chmod +x $file - exit 1 - fi - ;; - - bison|yacc) - echo 1>&2 "\ -WARNING: \`$1' $msg. You should only need it if - you modified a \`.y' file. You may need the \`Bison' package - in order for those modifications to take effect. You can get - \`Bison' from any GNU archive site." - rm -f y.tab.c y.tab.h - if test $# -ne 1; then - eval LASTARG="\${$#}" - case $LASTARG in - *.y) - SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" y.tab.c - fi - SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" y.tab.h - fi - ;; - esac - fi - if test ! -f y.tab.h; then - echo >y.tab.h - fi - if test ! -f y.tab.c; then - echo 'main() { return 0; }' >y.tab.c - fi - ;; - - lex|flex) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.l' file. You may need the \`Flex' package - in order for those modifications to take effect. You can get - \`Flex' from any GNU archive site." - rm -f lex.yy.c - if test $# -ne 1; then - eval LASTARG="\${$#}" - case $LASTARG in - *.l) - SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` - if test -f "$SRCFILE"; then - cp "$SRCFILE" lex.yy.c - fi - ;; - esac - fi - if test ! -f lex.yy.c; then - echo 'main() { return 0; }' >lex.yy.c - fi - ;; - - help2man) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a dependency of a manual page. You may need the - \`Help2man' package in order for those modifications to take - effect. You can get \`Help2man' from any GNU archive site." - - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -f "$file"; then - touch $file - else - test -z "$file" || exec >$file - echo ".ab help2man is required to generate this page" - exit 1 - fi - ;; - - makeinfo) - echo 1>&2 "\ -WARNING: \`$1' is $msg. You should only need it if - you modified a \`.texi' or \`.texinfo' file, or any other file - indirectly affecting the aspect of the manual. The spurious - call might also be the consequence of using a buggy \`make' (AIX, - DU, IRIX). You might want to install the \`Texinfo' package or - the \`GNU make' package. Grab either from any GNU archive site." - # The file to touch is that specified with -o ... - file=`echo "$*" | sed -n "$sed_output"` - test -z "$file" && file=`echo "$*" | sed -n "$sed_minuso"` - if test -z "$file"; then - # ... or it is the one specified with @setfilename ... - infile=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` - file=`sed -n ' - /^@setfilename/{ - s/.* \([^ ]*\) *$/\1/ - p - q - }' $infile` - # ... or it is derived from the source name (dir/f.texi becomes f.info) - test -z "$file" && file=`echo "$infile" | sed 's,.*/,,;s,.[^.]*$,,'`.info - fi - # If the file does not exist, the user really needs makeinfo; - # let's fail without touching anything. - test -f $file || exit 1 - touch $file - ;; - - tar) - shift - - # We have already tried tar in the generic part. - # Look for gnutar/gtar before invocation to avoid ugly error - # messages. - if (gnutar --version > /dev/null 2>&1); then - gnutar "$@" && exit 0 - fi - if (gtar --version > /dev/null 2>&1); then - gtar "$@" && exit 0 - fi - firstarg="$1" - if shift; then - case $firstarg in - *o*) - firstarg=`echo "$firstarg" | sed s/o//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - case $firstarg in - *h*) - firstarg=`echo "$firstarg" | sed s/h//` - tar "$firstarg" "$@" && exit 0 - ;; - esac - fi - - echo 1>&2 "\ -WARNING: I can't seem to be able to run \`tar' with the given arguments. - You may want to install GNU tar or Free paxutils, or check the - command line arguments." - exit 1 - ;; - - *) - echo 1>&2 "\ -WARNING: \`$1' is needed, and is $msg. - You might have modified some files without having the - proper tools for further handling them. Check the \`README' file, - it often tells you about the needed prerequisites for installing - this package. You may also peek at any GNU archive site, in case - some other package would contain this missing \`$1' program." - exit 1 - ;; -esac - -exit 0 - -# Local variables: -# eval: (add-hook 'write-file-hooks 'time-stamp) -# time-stamp-start: "scriptversion=" -# time-stamp-format: "%:y-%02m-%02d.%02H" -# time-stamp-end: "$" -# End: diff --git a/Frameworks/WavPack/Files/pack.c b/Frameworks/WavPack/Files/pack.c index 3cb711c12..eb4c418cc 100644 --- a/Frameworks/WavPack/Files/pack.c +++ b/Frameworks/WavPack/Files/pack.c @@ -1585,7 +1585,7 @@ int pack_block (WavpackContext *wpc, int32_t *buffer) if (wps->dc.shaping_data) { if (wps->dc.shaping_samples != sample_count) - memcpy (wps->dc.shaping_data, wps->dc.shaping_data + sample_count, + memmove (wps->dc.shaping_data, wps->dc.shaping_data + sample_count, (wps->dc.shaping_samples - sample_count) * sizeof (*wps->dc.shaping_data)); wps->dc.shaping_samples -= sample_count; diff --git a/Frameworks/WavPack/Files/tags.c b/Frameworks/WavPack/Files/tags.c index 38c082875..56403ecba 100644 --- a/Frameworks/WavPack/Files/tags.c +++ b/Frameworks/WavPack/Files/tags.c @@ -19,7 +19,7 @@ #define stricmp(x,y) _stricmp(x,y) #define fileno _fileno #else -#define stricmp(x,y) strcasecmp(x,y) +#define stricmp strcasecmp #endif #ifdef DEBUG_ALLOC @@ -198,10 +198,9 @@ int WavpackDeleteTagItem (WavpackContext *wpc, const char *item) int i; for (i = 0; i < m_tag->ape_tag_hdr.item_count; ++i) { - int vsize, flags, isize; + int vsize, isize; - vsize = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24); p += 4; - flags = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24); p += 4; + vsize = p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24); p += 8; // skip flags because we don't need them for (isize = 0; p[isize] && p + isize < q; ++isize); if (vsize < 0 || vsize > m_tag->ape_tag_hdr.length || p + isize + vsize + 1 > q) @@ -230,13 +229,14 @@ int WavpackDeleteTagItem (WavpackContext *wpc, const char *item) // Once a APEv2 tag has been created with WavpackAppendTag(), this function is // used to write the completed tag to the end of the WavPack file. Note that // this function uses the same "blockout" function that is used to write -// regular WavPack blocks, although that's where the similarity ends. +// regular WavPack blocks, although that's where the similarity ends. It is also +// used to write tags that have been edited on existing files. int WavpackWriteTag (WavpackContext *wpc) { - if (wpc->blockout) + if (wpc->blockout) // this is the case for creating fresh WavPack files return write_tag_blockout (wpc); - else + else // otherwise we are editing existing tags (OPEN_EDIT_TAGS) return write_tag_reader (wpc); } @@ -256,15 +256,25 @@ int load_tag (WavpackContext *wpc) CLEAR (*m_tag); + // This is a loop because we can try up to three times to look for an APEv2 tag. In order, we look: + // + // 1. At the end of the file for a APEv2 footer (this is the preferred location) + // 2. If there's instead an ID3v1 tag at the end of the file, try looking for an APEv2 footer right before that + // 3. If all else fails, look for an APEv2 header the the beginning of the file (use is strongly discouraged) + while (1) { - // attempt to find an APEv2 tag either at end-of-file or before a ID3v1 tag we found + // seek based on specific location that we are looking for tag (see above list) - if (m_tag->id3_tag.tag_id [0] == 'T') + if (m_tag->tag_begins_file) // case #3 + wpc->reader->set_pos_abs (wpc->wv_in, 0); + else if (m_tag->id3_tag.tag_id [0] == 'T') // case #2 wpc->reader->set_pos_rel (wpc->wv_in, -(int32_t)(sizeof (APE_Tag_Hdr) + sizeof (ID3_Tag)), SEEK_END); - else + else // case #1 wpc->reader->set_pos_rel (wpc->wv_in, -(int32_t)sizeof (APE_Tag_Hdr), SEEK_END); + // read a possible APEv2 tag header/footer and see if there's one there... + if (wpc->reader->read_bytes (wpc->wv_in, &m_tag->ape_tag_hdr, sizeof (APE_Tag_Hdr)) == sizeof (APE_Tag_Hdr) && !strncmp (m_tag->ape_tag_hdr.ID, "APETAGEX", 8)) { @@ -278,37 +288,41 @@ int load_tag (WavpackContext *wpc) ape_tag_items = m_tag->ape_tag_hdr.item_count; ape_tag_length = m_tag->ape_tag_hdr.length; - if (m_tag->id3_tag.tag_id [0] == 'T') - m_tag->tag_file_pos = -(int32_t)sizeof (ID3_Tag); - else - m_tag->tag_file_pos = 0; + // If this is a APEv2 footer (which is normal if we are searching at the end of the file)... - m_tag->tag_file_pos -= ape_tag_length; + if (!(m_tag->ape_tag_hdr.flags & APE_TAG_THIS_IS_HEADER)) { - // if the footer claims there is a header present also, we will read that and use it - // instead of the footer (after verifying it, of course) for enhanced robustness + if (m_tag->id3_tag.tag_id [0] == 'T') + m_tag->tag_file_pos = -(int32_t)sizeof (ID3_Tag); + else + m_tag->tag_file_pos = 0; - if (m_tag->ape_tag_hdr.flags & APE_TAG_CONTAINS_HEADER) - m_tag->tag_file_pos -= sizeof (APE_Tag_Hdr); + m_tag->tag_file_pos -= ape_tag_length; - wpc->reader->set_pos_rel (wpc->wv_in, m_tag->tag_file_pos, SEEK_END); - memset (m_tag->ape_tag_data, 0, ape_tag_length); + // if the footer claims there is a header present also, we will read that and use it + // instead of the footer (after verifying it, of course) for enhanced robustness - if (m_tag->ape_tag_hdr.flags & APE_TAG_CONTAINS_HEADER) { - if (wpc->reader->read_bytes (wpc->wv_in, &m_tag->ape_tag_hdr, sizeof (APE_Tag_Hdr)) != - sizeof (APE_Tag_Hdr) || strncmp (m_tag->ape_tag_hdr.ID, "APETAGEX", 8)) { - free (m_tag->ape_tag_data); - CLEAR (*m_tag); - return FALSE; // something's wrong... - } + if (m_tag->ape_tag_hdr.flags & APE_TAG_CONTAINS_HEADER) + m_tag->tag_file_pos -= sizeof (APE_Tag_Hdr); - little_endian_to_native (&m_tag->ape_tag_hdr, APE_Tag_Hdr_Format); + wpc->reader->set_pos_rel (wpc->wv_in, m_tag->tag_file_pos, SEEK_END); - if (m_tag->ape_tag_hdr.version != 2000 || m_tag->ape_tag_hdr.item_count != ape_tag_items || - m_tag->ape_tag_hdr.length != ape_tag_length) { - free (m_tag->ape_tag_data); - CLEAR (*m_tag); - return FALSE; // something's wrong... + if (m_tag->ape_tag_hdr.flags & APE_TAG_CONTAINS_HEADER) { + if (wpc->reader->read_bytes (wpc->wv_in, &m_tag->ape_tag_hdr, sizeof (APE_Tag_Hdr)) != + sizeof (APE_Tag_Hdr) || strncmp (m_tag->ape_tag_hdr.ID, "APETAGEX", 8)) { + free (m_tag->ape_tag_data); + CLEAR (*m_tag); + return FALSE; // something's wrong... + } + + little_endian_to_native (&m_tag->ape_tag_hdr, APE_Tag_Hdr_Format); + + if (m_tag->ape_tag_hdr.version != 2000 || m_tag->ape_tag_hdr.item_count != ape_tag_items || + m_tag->ape_tag_hdr.length != ape_tag_length) { + free (m_tag->ape_tag_data); + CLEAR (*m_tag); + return FALSE; // something's wrong... + } } } @@ -325,22 +339,37 @@ int load_tag (WavpackContext *wpc) } } + // we come here if the search for the APEv2 tag failed (otherwise we would have returned with it) + if (m_tag->id3_tag.tag_id [0] == 'T') { // settle for the ID3v1 tag that we found CLEAR (m_tag->ape_tag_hdr); return TRUE; } - // look for ID3v1 tag if APEv2 tag not found during first pass + // if this was the search for the APEv2 tag at the beginning of the file (which is our + // last resort) then we have nothing, so return failure + + if (m_tag->tag_begins_file) { + CLEAR (*m_tag); + return FALSE; + } + + // If we get here, then we have failed the first APEv2 tag search (at end of file) and so now we + // look for an ID3v1 tag at the same position. If that succeeds, then we'll loop back and look for + // an APEv2 tag immediately before the ID3v1 tag, otherwise our last resort is to look for an + // APEv2 tag at the beginning of the file. These are strongly discouraged (and not editable) but + // they have been seen in the wild so we attempt to handle them here (at least well enough to + // allow a proper transcoding). m_tag->tag_file_pos = -(int32_t)sizeof (ID3_Tag); wpc->reader->set_pos_rel (wpc->wv_in, m_tag->tag_file_pos, SEEK_END); if (wpc->reader->read_bytes (wpc->wv_in, &m_tag->id3_tag, sizeof (ID3_Tag)) != sizeof (ID3_Tag) || strncmp (m_tag->id3_tag.tag_id, "TAG", 3)) { - CLEAR (*m_tag); - return FALSE; // neither type of tag found - } - } + m_tag->tag_begins_file = 1; // failed ID3v1, so look for APEv2 at beginning of file + CLEAR (m_tag->id3_tag); + } + } } // Return TRUE is a valid ID3v1 or APEv2 tag has been loaded. @@ -355,6 +384,14 @@ int valid_tag (M_Tag *m_tag) return 0; } +// Return FALSE if a valid APEv2 tag was only found at the beginning of the file (these are read-only +// because they cannot be edited without possibly shifting the entire file) + +int editable_tag (M_Tag *m_tag) +{ + return !m_tag->tag_begins_file; +} + // Free the data for any APEv2 tag that was allocated. void free_tag (M_Tag *m_tag) @@ -623,7 +660,24 @@ static int write_tag_reader (WavpackContext *wpc) { M_Tag *m_tag = &wpc->m_tag; int32_t tag_size = 0; - int result = TRUE; + int result; + + // before we write an edited (or new) tag into an existing file, make sure it's safe and possible + + if (m_tag->tag_begins_file) { + strcpy (wpc->error_message, "can't edit tags located at the beginning of files!"); + return FALSE; + } + + if (!wpc->reader->can_seek (wpc->wv_in)) { + strcpy (wpc->error_message, "can't edit tags on pipes or unseekable files!"); + return FALSE; + } + + if (!(wpc->open_flags & OPEN_EDIT_TAGS)) { + strcpy (wpc->error_message, "can't edit tags without OPEN_EDIT_TAGS flag!"); + return FALSE; + } if (m_tag->ape_tag_hdr.ID [0] == 'A' && m_tag->ape_tag_hdr.item_count && m_tag->ape_tag_hdr.length > sizeof (m_tag->ape_tag_hdr)) @@ -634,8 +688,7 @@ static int write_tag_reader (WavpackContext *wpc) if (m_tag->ape_tag_hdr.flags & APE_TAG_CONTAINS_HEADER) tag_size += sizeof (m_tag->ape_tag_hdr); - result = (wpc->open_flags & OPEN_EDIT_TAGS) && wpc->reader->can_seek (wpc->wv_in) && - !wpc->reader->set_pos_rel (wpc->wv_in, m_tag->tag_file_pos, SEEK_END); + result = !wpc->reader->set_pos_rel (wpc->wv_in, m_tag->tag_file_pos, SEEK_END); if (result && tag_size < -m_tag->tag_file_pos) { int nullcnt = -m_tag->tag_file_pos - tag_size; diff --git a/Frameworks/WavPack/Files/unpack3.c b/Frameworks/WavPack/Files/unpack3.c index eb4be0a18..d877a799e 100644 --- a/Frameworks/WavPack/Files/unpack3.c +++ b/Frameworks/WavPack/Files/unpack3.c @@ -61,7 +61,7 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error) if (wpc->reader->read_bytes (wpc->wv_in, &RiffChunkHeader, sizeof (RiffChunkHeader)) != sizeof (RiffChunkHeader)) { - strcpy (error, "not a valid WavPack file!"); + if (error) strcpy (error, "not a valid WavPack file!"); return WavpackCloseFile (wpc); } @@ -81,7 +81,7 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error) if (wpc->reader->read_bytes (wpc->wv_in, &ChunkHeader, sizeof (ChunkHeader)) != sizeof (ChunkHeader)) { - strcpy (error, "not a valid WavPack file!"); + if (error) strcpy (error, "not a valid WavPack file!"); return WavpackCloseFile (wpc); } else { @@ -97,7 +97,7 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error) if (ChunkHeader.ckSize < sizeof (wavhdr) || wpc->reader->read_bytes (wpc->wv_in, &wavhdr, sizeof (wavhdr)) != sizeof (wavhdr)) { - strcpy (error, "not a valid WavPack file!"); + if (error) strcpy (error, "not a valid WavPack file!"); return WavpackCloseFile (wpc); } else if (wpc->open_flags & OPEN_WRAPPER) { @@ -112,7 +112,7 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error) uint32_t bytes_to_skip = (ChunkHeader.ckSize + 1 - sizeof (wavhdr)) & ~1L; if (bytes_to_skip > 1024 * 1024) { - strcpy (error, "not a valid WavPack file!"); + if (error) strcpy (error, "not a valid WavPack file!"); return WavpackCloseFile (wpc); } @@ -134,7 +134,7 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error) uint32_t bytes_to_skip = (ChunkHeader.ckSize + 1) & ~1L; if (bytes_to_skip > 1024 * 1024) { - strcpy (error, "not a valid WavPack file!"); + if (error) strcpy (error, "not a valid WavPack file!"); return WavpackCloseFile (wpc); } @@ -153,7 +153,7 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error) } } else { - strcpy (error, "not a valid WavPack file!"); + if (error) strcpy (error, "not a valid WavPack file!"); return WavpackCloseFile (wpc); } @@ -161,7 +161,7 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error) !wavhdr.SampleRate || wavhdr.BitsPerSample < 16 || wavhdr.BitsPerSample > 24 || wavhdr.BlockAlign / wavhdr.NumChannels > 3 || wavhdr.BlockAlign % wavhdr.NumChannels || wavhdr.BlockAlign / wavhdr.NumChannels < (wavhdr.BitsPerSample + 7) / 8) { - strcpy (error, "not a valid WavPack file!"); + if (error) strcpy (error, "not a valid WavPack file!"); return WavpackCloseFile (wpc); } @@ -169,17 +169,17 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error) ((wavhdr.BitsPerSample > 16) ? 3 : 2); if (wpc->reader->read_bytes (wpc->wv_in, &wphdr, 10) != 10) { - strcpy (error, "not a valid WavPack file!"); + if (error) strcpy (error, "not a valid WavPack file!"); return WavpackCloseFile (wpc); } if (((char *) &wphdr) [8] == 2 && (wpc->reader->read_bytes (wpc->wv_in, ((char *) &wphdr) + 10, 2) != 2)) { - strcpy (error, "not a valid WavPack file!"); + if (error) strcpy (error, "not a valid WavPack file!"); return WavpackCloseFile (wpc); } else if (((char *) &wphdr) [8] == 3 && (wpc->reader->read_bytes (wpc->wv_in, ((char *) &wphdr) + 10, sizeof (wphdr) - 10) != sizeof (wphdr) - 10)) { - strcpy (error, "not a valid WavPack file!"); + if (error) strcpy (error, "not a valid WavPack file!"); return WavpackCloseFile (wpc); } @@ -188,7 +188,7 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error) // make sure this is a version we know about if (strncmp (wphdr.ckID, "wvpk", 4) || wphdr.version < 1 || wphdr.version > 3) { - strcpy (error, "not a valid WavPack file!"); + if (error) strcpy (error, "not a valid WavPack file!"); return WavpackCloseFile (wpc); } @@ -205,7 +205,7 @@ WavpackContext *open_file3 (WavpackContext *wpc, char *error) (((wphdr.flags & NEW_HIGH_FLAG) && (wphdr.flags & (FAST_FLAG | HIGH_FLAG))) || (wphdr.flags & CROSS_DECORR)))) { - strcpy (error, "not a valid WavPack file!"); + if (error) strcpy (error, "not a valid WavPack file!"); return WavpackCloseFile (wpc); } @@ -503,8 +503,8 @@ static int unpack_size (WavpackStream3 *wps) byte_sum += sizeof (wps->dc.weight); } - if (flags & (HIGH_FLAG | NEW_HIGH_FLAG)) { - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { + if (flags & (HIGH_FLAG | NEW_HIGH_FLAG)) + for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) if (dpp->term > 0) { byte_sum += sizeof (dpp->samples_A [0]) * dpp->term; byte_sum += sizeof (dpp->weight_A); @@ -518,8 +518,6 @@ static int unpack_size (WavpackStream3 *wps) byte_sum += sizeof (dpp->samples_A [0]) + sizeof (dpp->samples_B [0]); byte_sum += sizeof (dpp->weight_A) + sizeof (dpp->weight_B); } - } - } return byte_sum; } @@ -573,8 +571,8 @@ static void *unpack_save (WavpackStream3 *wps, void *destin) SAVE (destin, wps->dc.weight); } - if (flags & (HIGH_FLAG | NEW_HIGH_FLAG)) { - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { + if (flags & (HIGH_FLAG | NEW_HIGH_FLAG)) + for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) if (dpp->term > 0) { int count = dpp->term; int index = wps->dc.m; @@ -604,8 +602,6 @@ static void *unpack_save (WavpackStream3 *wps, void *destin) SAVE (destin, dpp->samples_A [0]); SAVE (destin, dpp->samples_B [0]); } - } - } return destin; } @@ -687,8 +683,8 @@ static void *unpack_restore (WavpackStream3 *wps, void *source, int keep_resourc RESTORE (wps->dc.weight, source); } - if (flags & (HIGH_FLAG | NEW_HIGH_FLAG)) { - for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) { + if (flags & (HIGH_FLAG | NEW_HIGH_FLAG)) + for (tcount = wps->num_terms, dpp = wps->decorr_passes; tcount--; dpp++) if (dpp->term > 0) { int count = dpp->term; int index = wps->dc.m; @@ -718,8 +714,6 @@ static void *unpack_restore (WavpackStream3 *wps, void *source, int keep_resourc RESTORE (dpp->samples_A [0], source); RESTORE (dpp->samples_B [0], source); } - } - } return source; } diff --git a/Frameworks/WavPack/Files/utils.c b/Frameworks/WavPack/Files/utils.c index 849b730c0..8ead3dfa5 100644 --- a/Frameworks/WavPack/Files/utils.c +++ b/Frameworks/WavPack/Files/utils.c @@ -12,6 +12,7 @@ // utilities and the self-extraction module. #if defined(WIN32) +#define WIN32_LEAN_AND_MEAN #include #include #include @@ -139,7 +140,7 @@ char *filespec_ext (char *filespec) while (--cp >= filespec) { - if (*cp == '/' || *cp == ':') + if (*cp == '/') return NULL; if (*cp == '.') { @@ -175,7 +176,7 @@ char *filespec_path (char *filespec) if (cp == filespec || filespec_wild (filespec)) return NULL; - if (*--cp == '/' || *cp == ':') + if (*--cp == '/') return filespec; if (*cp == '.' && cp == filespec) @@ -276,7 +277,7 @@ char *filespec_name (char *filespec) char *cp = filespec + strlen (filespec); while (--cp >= filespec) - if (*cp == '/' || *cp == ':') + if (*cp == '/') break; if (strlen (cp + 1)) @@ -333,6 +334,10 @@ char yna (void) fprintf (stderr, "^C\n"); exit (1); } + else if (key == EOF) { + fprintf (stderr, "\r\n"); + exit (1); + } else if (key == '\r' || key == '\n') { if (choice) { fprintf (stderr, "\r\n"); @@ -600,8 +605,24 @@ void finish_line (void) // Function to initialize console for intercepting ^C and ^Break. // ////////////////////////////////////////////////////////////////////////////// +#include + +static int break_flag; + +static void int_handler(int s) +{ + break_flag = 1; +} + void setup_break (void) { + struct sigaction sigIntHandler; + + break_flag = 0; + sigIntHandler.sa_handler = int_handler; + sigemptyset (&sigIntHandler.sa_mask); + sigIntHandler.sa_flags = 0; + sigaction (SIGINT, &sigIntHandler, NULL); } ////////////////////////////////////////////////////////////////////////////// @@ -610,7 +631,7 @@ void setup_break (void) int check_break (void) { - return 0; + return break_flag; } #endif @@ -661,12 +682,22 @@ int DoWriteFile (FILE *hFile, void *lpBuffer, uint32_t nNumberOfBytesToWrite, ui int64_t DoGetFileSize (FILE *hFile) { - struct stat64 statbuf; + LARGE_INTEGER Size; + HANDLE fHandle; - if (!hFile || fstat64 (fileno (hFile), &statbuf) || !(statbuf.st_mode & S_IFREG)) + if (hFile == NULL) return 0; - return statbuf.st_size; + fHandle = (HANDLE)_get_osfhandle(_fileno(hFile)); + if (fHandle == INVALID_HANDLE_VALUE) + return 0; + + Size.u.LowPart = GetFileSize(fHandle, &Size.u.HighPart); + + if (Size.u.LowPart == INVALID_FILE_SIZE && GetLastError() != NO_ERROR) + return 0; + + return (int64_t)Size.QuadPart; } #else @@ -727,6 +758,27 @@ int DoTruncateFile (FILE *hFile) int DoDeleteFile (char *filename) { - return !remove (filename); + return filename ? !remove (filename) : 0; } +///////////////////////////////////////////////////////////////////////////////// +// Function to set the name of the console window. This is very handy for // +// displaying progress of batch operations with the console window minimized. // +///////////////////////////////////////////////////////////////////////////////// + +#ifdef WIN32 + +void DoSetConsoleTitle (char *text) +{ + SetConsoleTitle (text); +} + +#else + +void DoSetConsoleTitle (char *text) +{ + fprintf (stderr, "\033]0;%s\007", text); +} + +#endif + diff --git a/Frameworks/WavPack/Files/utils.h b/Frameworks/WavPack/Files/utils.h index c23e92b78..7d60cee4f 100644 --- a/Frameworks/WavPack/Files/utils.h +++ b/Frameworks/WavPack/Files/utils.h @@ -23,8 +23,13 @@ #if defined(WIN32) #undef VERSION_OS +#ifdef _WIN64 +#define VERSION_OS "Win64" +#else #define VERSION_OS "Win32" #endif +#define PACKAGE_VERSION "4.70.0" +#endif #define FALSE 0 #define TRUE 1 @@ -49,6 +54,7 @@ int DoUngetc (int c, FILE *hFile); int DoCloseHandle (FILE *hFile); int DoTruncateFile (FILE *hFile); int DoDeleteFile (char *filename); +void DoSetConsoleTitle (char *text); #define FN_FIT(fn) ((strlen (fn) > 30) ? filespec_name (fn) : fn) diff --git a/Frameworks/WavPack/Files/wavpack.c b/Frameworks/WavPack/Files/wavpack.c index 31b484408..95a9728b4 100644 --- a/Frameworks/WavPack/Files/wavpack.c +++ b/Frameworks/WavPack/Files/wavpack.c @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////////////////////// // **** WAVPACK **** // // Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2009 Conifer Software. // +// Copyright (c) 1998 - 2013 Conifer Software. // // All Rights Reserved. // // Distributed under the BSD Software License (see license.txt) // //////////////////////////////////////////////////////////////////////////// @@ -11,6 +11,7 @@ // This is the main module for the WavPack command-line compressor. #if defined(WIN32) +#define WIN32_LEAN_AND_MEAN #include #include #else @@ -49,13 +50,7 @@ #define strdup(x) _strdup(x) #define fileno _fileno #else -#define stricmp(x,y) strcasecmp(x,y) -#endif - -#ifdef __APPLE__ -#define VERSION_OS_STRING "Darwin" -#else -#define VERSION_OS_STRING VERSION_OS +#define stricmp strcasecmp #endif #ifdef DEBUG_ALLOC @@ -74,21 +69,22 @@ static char *strdup (const char *s) static const char *sign_on = "\n" " WAVPACK Hybrid Lossless Audio Compressor %s Version %s\n" -" Copyright (c) 1998 - 2009 Conifer Software. All Rights Reserved.\n\n"; +" Copyright (c) 1998 - 2013 Conifer Software. All Rights Reserved.\n\n"; static const char *usage = #if defined (WIN32) -" Usage: WAVPACK [-options] [@]infile[.wav]|- [[@]outfile[.wv]|outpath|-]\n" +" Usage: WAVPACK [-options] infile[.wav]|infile.wv|- [outfile[.wv]|outpath|-]\n" " (default is lossless; infile may contain wildcards: ?,*)\n\n" #else -" Usage: WAVPACK [-options] [@]infile[.wav]|- [...] [-o [@]outfile[.wv]|outpath|-]\n" -" (default is lossless; infile(s) may contain wildcards: ?,*)\n\n" +" Usage: WAVPACK [-options] infile[.wav]|infile.wv|- [...] [-o outfile[.wv]|outpath|-]\n" +" (default is lossless; multiple input files allowed)\n\n" #endif " Options: -bn = enable hybrid compression, n = 2.0 to 23.9 bits/sample, or\n" " n = 24-9600 kbits/second (kbps)\n" " -c = create correction file (.wvc) for hybrid mode (=lossless)\n" " -f = fast mode (fast, but some compromise in compression ratio)\n" " -h = high quality (better compression ratio, but slower)\n" +" -v = verify output file integrity after write (no pipes)\n" " -x = extra encode processing (no decoding speed penalty)\n" " --help = complete help\n\n" " Web: Visit www.wavpack.com for latest version and info\n"; @@ -96,15 +92,22 @@ static const char *usage = static const char *help = #if defined (WIN32) " Usage:\n" -" WAVPACK [-options] [@]infile[.wav]|- [[@]outfile[.wv]|outpath|-]\n" -" (default operation is lossless; infile may contain wildcards: ?,*)\n\n" +" WAVPACK [-options] infile[.wav]|infile.wv|- [outfile[.wv]|outpath|-]\n\n" +" The default operation is lossless. Wildcard characters (*,?) may be included\n" +" in the input file and they may be either WAV or WAVPACK (.wv) files (or raw\n" +" PCM if --raw-pcm is included). When transcoding, all tags are copied.\n\n" #else " Usage:\n" -" WAVPACK [-options] [@]infile[.wav]|- [...] [-o [@]outfile[.wv]|outpath|-]\n" -" (default operation is lossless; infile(s) may contain wildcards: ?,*)\n\n" +" WAVPACK [-options] infile[.wav]|infile.wv|- [...] [-o outfile[.wv]|outpath|-]\n\n" +" The default operation is lossless. Multiple input files may be specified,\n" +" and they may be either WAV or WAVPACK (.wv) files (or raw PCM if --raw-pcm\n" +" is included). When transcoding, all tags are copied.\n\n" #endif " Options:\n" " -a Adobe Audition (CoolEdit) mode for 32-bit floats\n" +" --allow-huge-tags allow tag data up to 16 MB (embedding > 1 MB is not\n" +" recommended for portable devices and may not work\n" +" with some programs including WavPack pre-4.70)\n" " -bn enable hybrid compression\n" " n = 2.0 to 23.9 bits/sample, or\n" " n = 24-9600 kbits/second (kbps)\n" @@ -169,6 +172,8 @@ static const char *help = " in freq, use '0' for no shaping (white noise)\n" " -t copy input file's time stamp to output file(s)\n" " --use-dns force use of dynamic noise shaping (hybrid mode only)\n" +" -v verify output file integrity after write (no pipes)\n" +" --version write the version to stdout\n" " -w \"Field=Value\" write specified text metadata to APEv2 tag\n" " -w \"Field=@file.ext\" write specified text metadata from file to APEv2\n" " tag, normally used for embedded cuesheets and logs\n" @@ -180,7 +185,8 @@ static const char *help = " -x[n] extra encode processing (optional n = 1 to 6, 1=default)\n" " -x1 to -x3 to choose best of predefined filters\n" " -x4 to -x6 to generate custom filters (very slow!)\n" -" -y yes to all warnings (use with caution!)\n\n" +" -y yes to all warnings (use with caution!)\n" +" -z don't set console title to indicate progress\n\n" " Web:\n" " Visit www.wavpack.com for latest version and complete information\n"; @@ -196,12 +202,13 @@ static const char *speakers [] = { int debug_logging_mode; -static int overwrite_all, num_files, file_index, copy_time, quiet_mode, - adobe_mode, ignore_length, new_riff_header, do_md5_checksum, raw_pcm, no_utf8_convert; +static int overwrite_all, num_files, file_index, copy_time, quiet_mode, verify_mode, delete_source, store_floats_as_ints, + adobe_mode, ignore_length, new_riff_header, raw_pcm, no_utf8_convert, no_console_title, allow_huge_tags; static int num_channels_order; static unsigned char channel_order [18], channel_order_undefined; static uint32_t channel_order_mask; +static double encode_time_percent; // These two statics are used to keep track of tags that the user specifies on the // command line. The "num_tag_strings" and "tag_strings" fields in the WavpackConfig @@ -224,9 +231,12 @@ static uint32_t wvselfx_size; static FILE *wild_fopen (char *filename, const char *mode); static int pack_file (char *infilename, char *outfilename, char *out2filename, const WavpackConfig *config); -static int pack_audio (WavpackContext *wpc, FILE *infile, unsigned char *new_order); +static int pack_audio (WavpackContext *wpc, FILE *infile, unsigned char *new_order, unsigned char *md5_digest_source); +static int repack_file (char *infilename, char *outfilename, char *out2filename, const WavpackConfig *config); +static int repack_audio (WavpackContext *wpc, WavpackContext *infile, unsigned char *md5_digest_source); +static int verify_audio (char *infilename, unsigned char *md5_digest_source); static void display_progress (double file_progress); -static void AnsiToUTF8 (char *string, int len); +static void TextToUTF8 (void *string, int len); #define NO_ERROR 0L #define SOFT_ERROR 1 @@ -241,7 +251,7 @@ int main (argc, argv) int argc; char **argv; #ifdef __EMX__ /* OS/2 */ _wildcard (&argc, &argv); #endif - int delete_source = 0, error_count = 0, tag_next_arg = 0, output_spec = 0, ask_help = 0; + int error_count = 0, tag_next_arg = 0, output_spec = 0; char *outfilename = NULL, *out2filename = NULL; char **matches = NULL; WavpackConfig config; @@ -288,8 +298,15 @@ int main (argc, argv) int argc; char **argv; if (*long_param++ == '=') break; - if (!strcmp (long_option, "help")) // --help - ask_help = 1; + if (!strcmp (long_option, "help")) { // --help + printf ("%s", help); + return 1; + } + else if (!strcmp (long_option, "version")) { // --version + printf ("wavpack %s\n", PACKAGE_VERSION); + printf ("libwavpack %s\n", WavpackGetLibraryVersionString ()); + return 1; + } else if (!strcmp (long_option, "optimize-mono")) // --optimize-mono config.flags |= CONFIG_OPTIMIZE_MONO; else if (!strcmp (long_option, "dns")) { // --dns @@ -304,6 +321,10 @@ int main (argc, argv) int argc; char **argv; config.flags |= CONFIG_PAIR_UNDEF_CHANS; else if (!strcmp (long_option, "no-utf8-convert")) // --no-utf8-convert no_utf8_convert = 1; + else if (!strcmp (long_option, "allow-huge-tags")) // --allow-huge-tags + allow_huge_tags = 1; + else if (!strcmp (long_option, "store-floats-as-ints")) // --store-floats-as-ints + store_floats_as_ints = 1; else if (!strcmp (long_option, "write-binary-tag")) // --write-binary-tag tag_next_arg = 2; else if (!strncmp (long_option, "raw-pcm", 7)) { // --raw-pcm @@ -519,9 +540,12 @@ int main (argc, argv) int argc; char **argv; quiet_mode = 1; break; + case 'Z': case 'z': + no_console_title = 1; + break; + case 'M': case 'm': config.flags |= CONFIG_MD5_CHECKSUM; - do_md5_checksum = 1; break; case 'I': case 'i': @@ -532,6 +556,10 @@ int main (argc, argv) int argc; char **argv; new_riff_header = 1; break; + case 'V': case 'v': + verify_mode = 1; + break; + case 'B': case 'b': config.flags |= CONFIG_HYBRID_FLAG; config.bitrate = (float) strtod (++*argv, argv); @@ -674,7 +702,12 @@ int main (argc, argv) int argc; char **argv; if (ignore_length && outfilename && *outfilename == '-') { error_line ("can't ignore length in header when using stdout!"); ++error_count; - } + } + + if (verify_mode && outfilename && *outfilename == '-') { + error_line ("can't verify output file when using stdout!"); + ++error_count; + } if (config.flags & CONFIG_HYBRID_FLAG) { if ((config.flags & CONFIG_CREATE_WVC) && outfilename && *outfilename == '-') { @@ -709,7 +742,7 @@ int main (argc, argv) int argc; char **argv; } if (!quiet_mode && !error_count) - fprintf (stderr, sign_on, VERSION_OS_STRING, WavpackGetLibraryVersionString ()); + fprintf (stderr, sign_on, VERSION_OS, WavpackGetLibraryVersionString ()); // Loop through any tag specification strings and check for file access, convert text // strings to UTF-8, and otherwise prepare for writing to APE tags. This is done here @@ -749,16 +782,15 @@ int main (argc, argv) int argc; char **argv; if (filespec_ext (fn)) tag_items [i].ext = strdup (filespec_ext (fn)); - if (tag_items [i].vsize < 1048576) { - new_value = malloc (tag_items [i].vsize + 1); + if (tag_items [i].vsize < 1048576 * (allow_huge_tags ? 16 : 1)) { + new_value = malloc (tag_items [i].vsize + 2); + memset (new_value, 0, tag_items [i].vsize + 2); if (!DoReadFile (file, new_value, tag_items [i].vsize, &bcount) || bcount != tag_items [i].vsize) { free (new_value); new_value = NULL; } - else - new_value [tag_items [i].vsize] = 0; } DoCloseHandle (file); @@ -795,13 +827,13 @@ int main (argc, argv) int argc; char **argv; tag_items [i].value = realloc (tag_items [i].value, tag_items [i].vsize * 2 + 1); if (!no_utf8_convert) - AnsiToUTF8 (tag_items [i].value, (int) tag_items [i].vsize * 2 + 1); + TextToUTF8 (tag_items [i].value, (int) tag_items [i].vsize * 2 + 1); tag_items [i].vsize = (int) strlen (tag_items [i].value); } - if ((total_tag_size += tag_items [i].vsize) > 1048576) { - error_line ("total APEv2 tag size exceeds 1 MB !"); + if ((total_tag_size += tag_items [i].vsize) > 1048576 * (allow_huge_tags ? 16 : 1)) { + error_line ("total APEv2 tag size exceeds %d MB !", allow_huge_tags ? 16 : 1); ++error_count; break; } @@ -812,11 +844,6 @@ int main (argc, argv) int argc; char **argv; return 1; } - if (ask_help) { - printf ("%s", help); - return 1; - } - if (!num_files) { printf ("%s", usage); return 1; @@ -995,6 +1022,23 @@ int main (argc, argv) int argc; char **argv; if (num_files) { char outpath, addext; + // calculate an estimate for the percentage of the time that will be used for the encoding (as opposed + // to the optional verification step) based on the "extra" mode processing; this is only used for + // displaying the progress and so is not very critical + + if (verify_mode) { + if (config.flags & CONFIG_EXTRA_MODE) { + if (config.xmode) + encode_time_percent = 100.0 * (1.0 - (1.0 / ((1 << config.xmode) + 1))); + else + encode_time_percent = 66.7; + } + else + encode_time_percent = 50.0; + } + else + encode_time_percent = 100.0; + if (outfilename && *outfilename != '-') { outpath = (filespec_path (outfilename) != NULL); @@ -1058,10 +1102,13 @@ int main (argc, argv) int argc; char **argv; else out2filename = NULL; - if (num_files > 1) + if (num_files > 1 && !quiet_mode) fprintf (stderr, "\n%s:\n", matches [file_index]); - result = pack_file (matches [file_index], outfilename, out2filename, &config); + if (filespec_ext (matches [file_index]) && !stricmp (filespec_ext (matches [file_index]), ".wv")) + result = repack_file (matches [file_index], outfilename, out2filename, &config); + else + result = pack_file (matches [file_index], outfilename, out2filename, &config); if (result != NO_ERROR) ++error_count; @@ -1069,16 +1116,6 @@ int main (argc, argv) int argc; char **argv; if (result == HARD_ERROR) break; - // delete source file if that option is enabled - - if (result == NO_ERROR && delete_source) { - int res = DoDeleteFile (matches [file_index]); - - if (!quiet_mode || !res) - error_line ("%s source file %s", res ? - "deleted" : "can't delete", matches [file_index]); - } - // clean up in preparation for potentially another file if (outpath) @@ -1117,6 +1154,9 @@ int main (argc, argv) int argc; char **argv; error_line ("malloc_count = %d", dump_alloc ()); #endif + if (!no_console_title) + DoSetConsoleTitle ("WavPack Completed"); + return error_count ? 1 : 0; } @@ -1203,7 +1243,37 @@ static FILE *wild_fopen (char *filename, const char *mode) static FILE *wild_fopen (char *filename, const char *mode) { - return fopen (filename, mode); + char *matchname = NULL; + struct stat statbuf; + FILE *res = NULL; + glob_t globbuf; + int i; + + glob (filename, 0, NULL, &globbuf); + + for (i = 0; i < globbuf.gl_pathc; ++i) { + if (stat (globbuf.gl_pathv [i], &statbuf) == -1 || S_ISDIR (statbuf.st_mode)) + continue; + + if (matchname) { + free (matchname); + matchname = NULL; + break; + } + else { + matchname = malloc (strlen (globbuf.gl_pathv [i]) + 10); + strcpy (matchname, globbuf.gl_pathv [i]); + } + } + + globfree (&globbuf); + + if (matchname) { + res = fopen (matchname, mode); + free (matchname); + } + + return res; } #endif @@ -1216,10 +1286,13 @@ static FILE *wild_fopen (char *filename, const char *mode) static int pack_file (char *infilename, char *outfilename, char *out2filename, const WavpackConfig *config) { + char *outfilename_temp, *out2filename_temp, dummy; + int use_tempfiles = (out2filename != NULL); uint32_t total_samples = 0, bcount; WavpackConfig loc_config = *config; RiffChunkHeader riff_chunk_header; unsigned char *new_channel_order = NULL; + unsigned char md5_digest [16]; write_id wv_file, wvc_file; ChunkHeader chunk_header; WaveHeader WaveHeader; @@ -1282,40 +1355,118 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c // check both output files for overwrite warning required - if (*outfilename != '-' && !overwrite_all && (wv_file.file = fopen (outfilename, "rb")) != NULL) { + // note that for a file to be considered "overwritable", it must both be openable for reading + // and have at least 1 readable byte - this prevents us getting stuck on "nul" (Windows) + + if (*outfilename != '-' && (wv_file.file = fopen (outfilename, "rb")) != NULL) { + size_t res = fread (&dummy, 1, 1, wv_file.file); + DoCloseHandle (wv_file.file); - fprintf (stderr, "overwrite %s (yes/no/all)? ", FN_FIT (outfilename)); -#if defined(WIN32) - SetConsoleTitle ("overwrite?"); -#endif - switch (yna ()) { - case 'n': - DoCloseHandle (infile); - WavpackCloseFile (wpc); - return SOFT_ERROR; + if (res == 1) { + use_tempfiles = 1; - case 'a': - overwrite_all = 1; + if (!overwrite_all) { + fprintf (stderr, "overwrite %s (yes/no/all)? ", FN_FIT (outfilename)); + + if (!no_console_title) + DoSetConsoleTitle ("overwrite?"); + + switch (yna ()) { + case 'n': + DoCloseHandle (infile); + WavpackCloseFile (wpc); + return SOFT_ERROR; + + case 'a': + overwrite_all = 1; + } + } } } if (out2filename && !overwrite_all && (wvc_file.file = fopen (out2filename, "rb")) != NULL) { + size_t res = fread (&dummy, 1, 1, wvc_file.file); + DoCloseHandle (wvc_file.file); - fprintf (stderr, "overwrite %s (yes/no/all)? ", FN_FIT (out2filename)); -#if defined(WIN32) - SetConsoleTitle ("overwrite?"); -#endif - switch (yna ()) { + if (res == 1) { + fprintf (stderr, "overwrite %s (yes/no/all)? ", FN_FIT (out2filename)); - case 'n': - DoCloseHandle (infile); - WavpackCloseFile (wpc); - return SOFT_ERROR; + if (!no_console_title) + DoSetConsoleTitle ("overwrite?"); - case 'a': - overwrite_all = 1; + switch (yna ()) { + + case 'n': + DoCloseHandle (infile); + WavpackCloseFile (wpc); + return SOFT_ERROR; + + case 'a': + overwrite_all = 1; + } + } + } + + // if we are using temp files, either because the output filename already exists or we are creating a + // "correction" file, search for and generate the corresponding names here + + if (use_tempfiles) { + FILE *testfile; + int count = 0; + + outfilename_temp = malloc (strlen (outfilename) + 16); + + if (out2filename) + out2filename_temp = malloc (strlen (outfilename) + 16); + + while (1) { + strcpy (outfilename_temp, outfilename); + + if (filespec_ext (outfilename_temp)) { + if (count++) + sprintf (filespec_ext (outfilename_temp), ".tmp%d", count-1); + else + strcpy (filespec_ext (outfilename_temp), ".tmp"); + + strcat (outfilename_temp, filespec_ext (outfilename)); + } + else { + if (count++) + sprintf (outfilename_temp + strlen (outfilename_temp), ".tmp%d", count-1); + else + strcat (outfilename_temp, ".tmp"); + } + + testfile = fopen (outfilename_temp, "rb"); + + if (testfile) { + int res = (int) fread (&dummy, 1, 1, testfile); + + fclose (testfile); + + if (res == 1) + continue; + } + + if (out2filename) { + strcpy (out2filename_temp, outfilename_temp); + strcat (out2filename_temp, "c"); + + testfile = fopen (out2filename_temp, "rb"); + + if (testfile) { + int res = (int) fread (&dummy, 1, 1, testfile); + + fclose (testfile); + + if (res == 1) + continue; + } + } + + break; } } @@ -1336,8 +1487,8 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c setmode (fileno (stdout), O_BINARY); #endif } - else if ((wv_file.file = fopen (outfilename, "w+b")) == NULL) { - error_line ("can't create file %s!", outfilename); + else if ((wv_file.file = fopen (use_tempfiles ? outfilename_temp : outfilename, "w+b")) == NULL) { + error_line ("can't create file %s!", use_tempfiles ? outfilename_temp : outfilename); DoCloseHandle (infile); WavpackCloseFile (wpc); return SOFT_ERROR; @@ -1358,7 +1509,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c error_line ("can't write WavPack data, disk probably full!"); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); WavpackCloseFile (wpc); return SOFT_ERROR; } @@ -1373,7 +1524,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c error_line ("%s is not a valid .WAV file!", infilename); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); WavpackCloseFile (wpc); return SOFT_ERROR; } @@ -1382,7 +1533,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c error_line ("%s", WavpackGetErrorMessage (wpc)); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); WavpackCloseFile (wpc); return SOFT_ERROR; } @@ -1398,7 +1549,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c error_line ("%s is not a valid .WAV file!", infilename); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); WavpackCloseFile (wpc); return SOFT_ERROR; } @@ -1407,7 +1558,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c error_line ("%s", WavpackGetErrorMessage (wpc)); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); WavpackCloseFile (wpc); return SOFT_ERROR; } @@ -1426,7 +1577,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c error_line ("%s is not a valid .WAV file!", infilename); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); WavpackCloseFile (wpc); return SOFT_ERROR; } @@ -1435,7 +1586,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c error_line ("%s", WavpackGetErrorMessage (wpc)); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); WavpackCloseFile (wpc); return SOFT_ERROR; } @@ -1464,12 +1615,15 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c format = (WaveHeader.FormatTag == 0xfffe && chunk_header.ckSize == 40) ? WaveHeader.SubFormat : WaveHeader.FormatTag; - loc_config.bits_per_sample = chunk_header.ckSize == 40 ? + loc_config.bits_per_sample = (chunk_header.ckSize == 40 && WaveHeader.ValidBitsPerSample) ? WaveHeader.ValidBitsPerSample : WaveHeader.BitsPerSample; if (format != 1 && format != 3) supported = FALSE; + if (format == 3 && loc_config.bits_per_sample != 32 && !store_floats_as_ints) + supported = FALSE; + if (!WaveHeader.NumChannels || WaveHeader.NumChannels > 256 || WaveHeader.BlockAlign / WaveHeader.NumChannels < (loc_config.bits_per_sample + 7) / 8 || WaveHeader.BlockAlign / WaveHeader.NumChannels > 4 || @@ -1483,7 +1637,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c error_line ("%s is an unsupported .WAV format!", infilename); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); WavpackCloseFile (wpc); return SOFT_ERROR; } @@ -1496,20 +1650,18 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c else loc_config.channel_mask = 0x3ffff; } - else { + else if (WaveHeader.ChannelMask && (num_channels_order || channel_order_undefined)) { + error_line ("this WAV file already has channel order information!"); + DoCloseHandle (infile); + DoCloseHandle (wv_file.file); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); + WavpackCloseFile (wpc); + return SOFT_ERROR; + } + else loc_config.channel_mask = WaveHeader.ChannelMask; - if (num_channels_order || channel_order_undefined) { - error_line ("this WAV file already has channel order information!"); - DoCloseHandle (infile); - DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); - WavpackCloseFile (wpc); - return SOFT_ERROR; - } - } - - if (format == 3) + if (format == 3 && !store_floats_as_ints) loc_config.float_norm_exp = 127; else if (adobe_mode && WaveHeader.BlockAlign / WaveHeader.NumChannels == 4) { @@ -1538,7 +1690,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c error_line ("%s is not a valid .WAV file!", infilename); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); WavpackCloseFile (wpc); return SOFT_ERROR; } @@ -1547,7 +1699,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c error_line ("this .WAV file has over 16 MB of extra RIFF data, probably is corrupt!"); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); WavpackCloseFile (wpc); return SOFT_ERROR; } @@ -1558,7 +1710,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c error_line ("this .WAV file has no audio samples, probably is corrupt!"); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); WavpackCloseFile (wpc); return SOFT_ERROR; } @@ -1585,7 +1737,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c error_line ("%s", WavpackGetErrorMessage (wpc)); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); free (buff); WavpackCloseFile (wpc); return SOFT_ERROR; @@ -1603,7 +1755,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c error_line ("file does not have %d channel(s)!", num_channels_order); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); WavpackCloseFile (wpc); return SOFT_ERROR; } @@ -1637,7 +1789,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c error_line ("%s", WavpackGetErrorMessage (wpc)); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); WavpackCloseFile (wpc); return SOFT_ERROR; } @@ -1645,19 +1797,27 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c // if we are creating a "correction" file, open it now for writing if (out2filename) { - if ((wvc_file.file = fopen (out2filename, "w+b")) == NULL) { + if ((wvc_file.file = fopen (use_tempfiles ? out2filename_temp : out2filename, "w+b")) == NULL) { error_line ("can't create correction file!"); DoCloseHandle (infile); DoCloseHandle (wv_file.file); - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); WavpackCloseFile (wpc); return SOFT_ERROR; } } - // pack the audio portion of the file now + // pack the audio portion of the file now; calculate md5 if we're writing it to the file or verify mode is active - result = pack_audio (wpc, infile, new_channel_order); + result = pack_audio (wpc, infile, new_channel_order, ((loc_config.flags & CONFIG_MD5_CHECKSUM) || verify_mode) ? md5_digest : NULL); + + if (new_channel_order) + free (new_channel_order); + + // write the md5 sum if the user asked for it to be included + + if (result == NO_ERROR && (loc_config.flags & CONFIG_MD5_CHECKSUM)) + WavpackStoreMD5Sum (wpc, md5_digest); // if everything went well (and we're not ignoring length) try to read // anything else that might be appended to the audio data and write that @@ -1788,7 +1948,7 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c } } - // at this point we're done with the files, so close 'em whether there + // at this point we're completely done with the files, so close 'em whether there // were any other errors or not if (!DoCloseHandle (wv_file.file)) { @@ -1805,24 +1965,84 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c result = SOFT_ERROR; } - // if there were any errors, delete the output files, close the context, - // and return the error + // if there have been no errors up to now, and verify mode is enabled, do that now; only pass in the md5 if this + // was a lossless operation (either explicitly or because a high lossy bitrate resulted in lossless) + + if (result == NO_ERROR && verify_mode) + result = verify_audio (use_tempfiles ? outfilename_temp : outfilename, !WavpackLossyBlocks (wpc) ? md5_digest : NULL); + + // if there were any errors, delete the output files, close the context, and return the error if (result != NO_ERROR) { - DoDeleteFile (outfilename); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); if (out2filename) - DoDeleteFile (out2filename); + DoDeleteFile (use_tempfiles ? out2filename_temp : out2filename); WavpackCloseFile (wpc); return result; } + // if we were writing to a temp file because the target file already existed, + // do the rename / overwrite now (and if that fails, return the error) + + if (use_tempfiles) { +#if defined(WIN32) + FILE *temp; + + if (remove (outfilename) && (temp = fopen (outfilename, "rb"))) { + error_line ("can not remove file %s, result saved in %s!", outfilename, outfilename_temp); + result = SOFT_ERROR; + fclose (temp); + } + else +#endif + if (rename (outfilename_temp, outfilename)) { + error_line ("can not rename temp file %s to %s!", outfilename_temp, outfilename); + result = SOFT_ERROR; + } + + if (out2filename) { +#if defined(WIN32) + FILE *temp; + + if (remove (out2filename) && (temp = fopen (out2filename, "rb"))) { + error_line ("can not remove file %s, result saved in %s!", out2filename, out2filename_temp); + result = SOFT_ERROR; + fclose (temp); + } + else +#endif + if (rename (out2filename_temp, out2filename)) { + error_line ("can not rename temp file %s to %s!", out2filename_temp, out2filename); + result = SOFT_ERROR; + } + } + + free (outfilename_temp); + if (out2filename) free (out2filename_temp); + + if (result != NO_ERROR) { + WavpackCloseFile (wpc); + return result; + } + } + if (result == NO_ERROR && copy_time) if (!copy_timestamp (infilename, outfilename) || (out2filename && !copy_timestamp (infilename, out2filename))) error_line ("failure copying time stamp!"); + // delete source file if that option is enabled + + if (result == NO_ERROR && delete_source) { + int res = DoDeleteFile (infilename); + + if (!quiet_mode || !res) + error_line ("%s source file %s", res ? + "deleted" : "can't delete", infilename); + } + // compute and display the time consumed along with some other details of // the packing operation, and then return NO_ERROR @@ -1854,10 +2074,20 @@ static int pack_file (char *infilename, char *outfilename, char *out2filename, c if (!quiet_mode) { char *file, *fext, *oper, *cmode, cratio [16] = ""; + if (loc_config.flags & CONFIG_MD5_CHECKSUM) { + char md5_string [] = "original md5 signature: 00000000000000000000000000000000"; + int i; + + for (i = 0; i < 16; ++i) + sprintf (md5_string + 24 + (i * 2), "%02x", md5_digest [i]); + + error_line (md5_string); + } + if (outfilename && *outfilename != '-') { file = FN_FIT (outfilename); fext = wvc_file.bytes_written ? " (+.wvc)" : ""; - oper = "created"; + oper = verify_mode ? "created (and verified)" : "created"; } else { file = (*infilename == '-') ? "stdin" : FN_FIT (infilename); @@ -1896,7 +2126,7 @@ static void reorder_channels (void *data, unsigned char *new_order, int num_chan #define INPUT_SAMPLES 65536 -static int pack_audio (WavpackContext *wpc, FILE *infile, unsigned char *new_order) +static int pack_audio (WavpackContext *wpc, FILE *infile, unsigned char *new_order, unsigned char *md5_digest_source) { uint32_t samples_remaining, input_samples = INPUT_SAMPLES, samples_read = 0; double progress = -1.0; @@ -1910,7 +2140,7 @@ static int pack_audio (WavpackContext *wpc, FILE *infile, unsigned char *new_ord while (input_samples * sizeof (int32_t) * WavpackGetNumChannels (wpc) > 2048*1024) input_samples >>= 1; - if (do_md5_checksum) + if (md5_digest_source) MD5Init (&md5_context); WavpackPackInit (wpc); @@ -1936,7 +2166,7 @@ static int pack_audio (WavpackContext *wpc, FILE *infile, unsigned char *new_ord reorder_channels (input_buffer, new_order, WavpackGetNumChannels (wpc), sample_count, WavpackGetBytesPerSample (wpc)); - if (do_md5_checksum) + if (md5_digest_source) MD5Update (&md5_context, input_buffer, sample_count * bytes_per_sample); if (!sample_count) @@ -1989,19 +2219,22 @@ static int pack_audio (WavpackContext *wpc, FILE *infile, unsigned char *new_ord } if (check_break ()) { +#if defined(WIN32) fprintf (stderr, "^C\n"); +#else + fprintf (stderr, "\n"); +#endif free (sample_buffer); free (input_buffer); return SOFT_ERROR; } if (WavpackGetProgress (wpc) != -1.0 && - progress != floor (WavpackGetProgress (wpc) * 100.0 + 0.5)) { + progress != floor (WavpackGetProgress (wpc) * encode_time_percent + 0.5)) { int nobs = progress == -1.0; - progress = WavpackGetProgress (wpc); - display_progress (progress); - progress = floor (progress * 100.0 + 0.5); + progress = floor (WavpackGetProgress (wpc) * encode_time_percent + 0.5); + display_progress (progress / 100.0); if (!quiet_mode) fprintf (stderr, "%s%3d%% done...", @@ -2017,20 +2250,650 @@ static int pack_audio (WavpackContext *wpc, FILE *infile, unsigned char *new_ord return HARD_ERROR; } - if (do_md5_checksum) { - char md5_string [] = "original md5 signature: 00000000000000000000000000000000"; - unsigned char md5_digest [16]; - int i; + if (md5_digest_source) + MD5Final (md5_digest_source, &md5_context); - MD5Final (md5_digest, &md5_context); + return NO_ERROR; +} - for (i = 0; i < 16; ++i) - sprintf (md5_string + 24 + (i * 2), "%02x", md5_digest [i]); +// This function transcodes a single WavPack file "infilename" and stores the resulting +// WavPack file at "outfilename". If "out2filename" is specified, then the "correction" +// file would go there. The files are opened and closed in this function and the "config" +// structure specifies the mode of compression. Note that lossy to lossless transcoding +// is not allowed (no technical reason, it's just dumb, and could result in files that +// fail their MD5 verification test). + +static int repack_file (char *infilename, char *outfilename, char *out2filename, const WavpackConfig *config) +{ + int output_lossless = !(config->flags & CONFIG_HYBRID_FLAG) || (config->flags & CONFIG_CREATE_WVC); + int use_tempfiles = (out2filename != NULL), input_mode; + unsigned char md5_verify [16], md5_display [16]; + char *outfilename_temp, *out2filename_temp; + uint32_t total_samples = 0, bcount; + WavpackConfig loc_config = *config; + WavpackContext *infile, *outfile; + write_id wv_file, wvc_file; + char error [80]; + double dtime; + int result; + +#if defined(WIN32) + struct _timeb time1, time2; +#else + struct timeval time1, time2; + struct timezone timez; +#endif + + // use library to open input WavPack file + + infile = WavpackOpenFileInput (infilename, error, OPEN_WVC | OPEN_TAGS | OPEN_WRAPPER, 0); + + if (!infile) { + error_line (error); + return SOFT_ERROR; + } + + input_mode = WavpackGetMode (infile); + + if (!(input_mode & MODE_LOSSLESS) && output_lossless) { + error_line ("can't transcode lossy file %s to lossless...not allowed!", infilename); + WavpackCloseFile (infile); + return SOFT_ERROR; + } + + total_samples = WavpackGetNumSamples (infile); + + if (total_samples == (uint32_t) -1) { + error_line ("can't transcode file %s of unknown length!", infilename); + WavpackCloseFile (infile); + return SOFT_ERROR; + } + + // open an output context + + CLEAR (wv_file); + CLEAR (wvc_file); + outfile = WavpackOpenFileOutput (write_block, &wv_file, out2filename ? &wvc_file : NULL); + + // check both output files for overwrite warning required + + if (*outfilename != '-' && (wv_file.file = fopen (outfilename, "rb")) != NULL) { + DoCloseHandle (wv_file.file); + use_tempfiles = 1; + + if (!overwrite_all) { + if (output_lossless) + fprintf (stderr, "overwrite %s (yes/no/all)? ", FN_FIT (outfilename)); + else + fprintf (stderr, "overwrite %s with lossy transcode (yes/no/all)? ", FN_FIT (outfilename)); + + if (!no_console_title) + DoSetConsoleTitle ("overwrite?"); + + switch (yna ()) { + case 'n': + WavpackCloseFile (infile); + WavpackCloseFile (outfile); + return SOFT_ERROR; + + case 'a': + overwrite_all = 1; + } + } + } + + if (out2filename && !overwrite_all && (wvc_file.file = fopen (out2filename, "rb")) != NULL) { + DoCloseHandle (wvc_file.file); + fprintf (stderr, "overwrite %s (yes/no/all)? ", FN_FIT (out2filename)); + + if (!no_console_title) + DoSetConsoleTitle ("overwrite?"); + + switch (yna ()) { + + case 'n': + WavpackCloseFile (infile); + WavpackCloseFile (outfile); + return SOFT_ERROR; + + case 'a': + overwrite_all = 1; + } + } + + // if we are using temp files, either because the output filename already exists or we are creating a + // "correction" file, search for and generate the corresponding names here + + if (use_tempfiles) { + FILE *testfile; + int count = 0; + + outfilename_temp = malloc (strlen (outfilename) + 16); + + if (out2filename) + out2filename_temp = malloc (strlen (outfilename) + 16); + + while (1) { + strcpy (outfilename_temp, outfilename); + + if (filespec_ext (outfilename_temp)) { + if (count++) + sprintf (filespec_ext (outfilename_temp), ".tmp%d", count-1); + else + strcpy (filespec_ext (outfilename_temp), ".tmp"); + + strcat (outfilename_temp, filespec_ext (outfilename)); + } + else { + if (count++) + sprintf (outfilename_temp + strlen (outfilename_temp), ".tmp%d", count-1); + else + strcat (outfilename_temp, ".tmp"); + } + + testfile = fopen (outfilename_temp, "rb"); + + if (testfile) { + fclose (testfile); + continue; + } + + if (out2filename) { + strcpy (out2filename_temp, outfilename_temp); + strcat (out2filename_temp, "c"); + + testfile = fopen (out2filename_temp, "rb"); + + if (testfile) { + fclose (testfile); + continue; + } + } + + break; + } + } + +#if defined(WIN32) + _ftime (&time1); +#else + gettimeofday(&time1,&timez); +#endif + + // open output file for writing + + if (*outfilename == '-') { + wv_file.file = stdout; +#if defined(WIN32) + _setmode (fileno (stdout), O_BINARY); +#endif +#if defined(__OS2__) + setmode (fileno (stdout), O_BINARY); +#endif + } + else if ((wv_file.file = fopen (use_tempfiles ? outfilename_temp : outfilename, "w+b")) == NULL) { + error_line ("can't create file %s!", use_tempfiles ? outfilename_temp : outfilename); + WavpackCloseFile (infile); + WavpackCloseFile (outfile); + return SOFT_ERROR; + } + + if (!quiet_mode) { + if (*outfilename == '-') + fprintf (stderr, "packing %s to stdout,", *infilename == '-' ? "stdin" : FN_FIT (infilename)); + else if (out2filename) + fprintf (stderr, "creating %s (+%s),", FN_FIT (outfilename), filespec_ext (out2filename)); + else + fprintf (stderr, "creating %s,", FN_FIT (outfilename)); + } + +#if defined (WIN32) + if (loc_config.flags & CONFIG_CREATE_EXE) + if (!DoWriteFile (wv_file.file, wvselfx_image, wvselfx_size, &bcount) || bcount != wvselfx_size) { + error_line ("can't write WavPack data, disk probably full!"); + WavpackCloseFile (infile); + DoCloseHandle (wv_file.file); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); + WavpackCloseFile (outfile); + return SOFT_ERROR; + } +#endif + + // unless we've been specifically told not to, copy RIFF header + + if (!new_riff_header && WavpackGetWrapperBytes (infile)) { + if (!WavpackAddWrapper (outfile, WavpackGetWrapperData (infile), WavpackGetWrapperBytes (infile))) { + error_line ("%s", WavpackGetErrorMessage (outfile)); + WavpackCloseFile (infile); + DoCloseHandle (wv_file.file); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); + WavpackCloseFile (outfile); + return SOFT_ERROR; + } + + WavpackFreeWrapper (infile); + } + + loc_config.bytes_per_sample = WavpackGetBytesPerSample (infile); + loc_config.bits_per_sample = WavpackGetBitsPerSample (infile); + loc_config.channel_mask = WavpackGetChannelMask (infile); + loc_config.num_channels = WavpackGetNumChannels (infile); + loc_config.sample_rate = WavpackGetSampleRate (infile); + + if (input_mode & MODE_FLOAT) + loc_config.float_norm_exp = WavpackGetFloatNormExp (infile); + + if (input_mode & MODE_MD5) + loc_config.flags |= CONFIG_MD5_CHECKSUM; + + if (!WavpackSetConfiguration (outfile, &loc_config, total_samples)) { + error_line ("%s", WavpackGetErrorMessage (outfile)); + WavpackCloseFile (infile); + DoCloseHandle (wv_file.file); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); + WavpackCloseFile (outfile); + return SOFT_ERROR; + } + + // if we are creating a "correction" file, open it now for writing + + if (out2filename) { + if ((wvc_file.file = fopen (use_tempfiles ? out2filename_temp : out2filename, "w+b")) == NULL) { + error_line ("can't create correction file!"); + WavpackCloseFile (infile); + DoCloseHandle (wv_file.file); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); + WavpackCloseFile (outfile); + return SOFT_ERROR; + } + } + + // pack the audio portion of the file now; calculate md5 if we're writing it to the file or verify mode is active + + result = repack_audio (outfile, infile, md5_verify); + + // before anything else, make sure the source file was read without errors + + if (result == NO_ERROR) { + if (WavpackGetNumErrors (infile)) { + error_line ("missing data or crc errors detected in %d block(s)!", WavpackGetNumErrors (infile)); + result = SOFT_ERROR; + } + + if (WavpackGetNumSamples (outfile) != total_samples) { + error_line ("incorrect number of samples read from source file!"); + result = SOFT_ERROR; + } + + if (input_mode & MODE_LOSSLESS) { + unsigned char md5_source [16]; + + if (WavpackGetMD5Sum (infile, md5_source) && memcmp (md5_source, md5_verify, sizeof (md5_source))) { + error_line ("MD5 signature in source should match, but does not!"); + result = SOFT_ERROR; + } + } + } + + // copy the md5 sum if present in source; if there's not one there and the user asked to add it, + // store the one we just calculated + + if (result == NO_ERROR) { + if (WavpackGetMD5Sum (infile, md5_display)) { + if (input_mode & MODE_LOSSLESS) + memcpy (md5_verify, md5_display, sizeof (md5_verify)); + + WavpackStoreMD5Sum (outfile, md5_display); + } + else if (loc_config.flags & CONFIG_MD5_CHECKSUM) { + memcpy (md5_display, md5_verify, sizeof (md5_display)); + WavpackStoreMD5Sum (outfile, md5_verify); + } + } + + // unless we've been specifically told not to, copy RIFF trailer + + if (result == NO_ERROR && !new_riff_header && WavpackGetWrapperBytes (infile)) { + if (!WavpackAddWrapper (outfile, WavpackGetWrapperData (infile), WavpackGetWrapperBytes (infile))) { + error_line ("%s", WavpackGetErrorMessage (outfile)); + WavpackCloseFile (infile); + DoCloseHandle (wv_file.file); + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); + WavpackCloseFile (outfile); + return SOFT_ERROR; + } + + WavpackFreeWrapper (infile); + } + + // we're now done with any WavPack blocks, so flush any remaining data + + if (result == NO_ERROR && !WavpackFlushSamples (outfile)) { + error_line ("%s", WavpackGetErrorMessage (outfile)); + result = HARD_ERROR; + } + + // if still no errors, check to see if we need to create & write a tag + // (which is NOT stored in regular WavPack blocks) + + if (result == NO_ERROR && ((input_mode & MODE_VALID_TAG) || num_tag_items)) { + int num_binary_items = WavpackGetNumBinaryTagItems (infile); + int num_items = WavpackGetNumTagItems (infile), i; + int item_len, value_len; + char *item, *value; + int res = TRUE; + + for (i = 0; i < num_items && res; ++i) { + item_len = WavpackGetTagItemIndexed (infile, i, NULL, 0); + item = malloc (item_len + 1); + WavpackGetTagItemIndexed (infile, i, item, item_len + 1); + value_len = WavpackGetTagItem (infile, item, NULL, 0); + value = malloc (value_len * 2 + 1); + WavpackGetTagItem (infile, item, value, value_len + 1); + res = WavpackAppendTagItem (outfile, item, value, value_len); + free (value); + free (item); + } + + for (i = 0; i < num_binary_items && res; ++i) { + item_len = WavpackGetBinaryTagItemIndexed (infile, i, NULL, 0); + item = malloc (item_len + 1); + WavpackGetBinaryTagItemIndexed (infile, i, item, item_len + 1); + value_len = WavpackGetBinaryTagItem (infile, item, NULL, 0); + value = malloc (value_len); + value_len = WavpackGetBinaryTagItem (infile, item, value, value_len); + res = WavpackAppendBinaryTagItem (outfile, item, value, value_len); + free (value); + free (item); + } + + for (i = 0; i < num_tag_items && res; ++i) + if (tag_items [i].vsize) { + if (tag_items [i].binary) + res = WavpackAppendBinaryTagItem (outfile, tag_items [i].item, tag_items [i].value, tag_items [i].vsize); + else + res = WavpackAppendTagItem (outfile, tag_items [i].item, tag_items [i].value, tag_items [i].vsize); + } + else + WavpackDeleteTagItem (outfile, tag_items [i].item); + + if (!res || !WavpackWriteTag (outfile)) { + error_line ("%s", WavpackGetErrorMessage (outfile)); + result = HARD_ERROR; + } + } + + WavpackCloseFile (infile); // we're now done with input file, so close + + // at this point we're completely done with the files, so close 'em whether there + // were any other errors or not + + if (!DoCloseHandle (wv_file.file)) { + error_line ("can't close WavPack file!"); + + if (result == NO_ERROR) + result = SOFT_ERROR; + } + + if (out2filename && !DoCloseHandle (wvc_file.file)) { + error_line ("can't close correction file!"); + + if (result == NO_ERROR) + result = SOFT_ERROR; + } + + // if there have been no errors up to now, and verify mode is enabled, do that now; only pass in the md5 if this + // was a lossless operation (either explicitly or because a high lossy bitrate resulted in lossless) + + if (result == NO_ERROR && verify_mode) + result = verify_audio (use_tempfiles ? outfilename_temp : outfilename, !WavpackLossyBlocks (outfile) ? md5_verify : NULL); + + // if there were any errors, delete the output files, close the context, and return the error + + if (result != NO_ERROR) { + DoDeleteFile (use_tempfiles ? outfilename_temp : outfilename); + + if (out2filename) + DoDeleteFile (use_tempfiles ? out2filename_temp : out2filename); + + WavpackCloseFile (outfile); + return result; + } + + if (result == NO_ERROR && copy_time) + if (!copy_timestamp (infilename, use_tempfiles ? outfilename_temp : outfilename) || + (out2filename && !copy_timestamp (infilename, use_tempfiles ? out2filename_temp : out2filename))) + error_line ("failure copying time stamp!"); + + // delete source file(s) if that option is enabled (this is done before temp file rename to make sure + // we don't delete the file(s) we just created) + + if (result == NO_ERROR && delete_source) { + int res; + + if (stricmp (infilename, outfilename)) { + res = DoDeleteFile (infilename); + + if (!quiet_mode || !res) + error_line ("%s source file %s", res ? + "deleted" : "can't delete", infilename); + } + + if (input_mode & MODE_WVC) { + char in2filename [PATH_MAX]; + + strcpy (in2filename, infilename); + strcat (in2filename, "c"); + + if (!out2filename || stricmp (in2filename, out2filename)) { + res = DoDeleteFile (in2filename); + + if (!quiet_mode || !res) + error_line ("%s source file %s", res ? + "deleted" : "can't delete", in2filename); + } + } + } + + // if we were writing to a temp file because the target file already existed, + // do the rename / overwrite now (and if that fails, return the error) + + if (use_tempfiles) { +#if defined(WIN32) + FILE *temp; + + if (remove (outfilename) && (temp = fopen (outfilename, "rb"))) { + error_line ("can not remove file %s, result saved in %s!", outfilename, outfilename_temp); + result = SOFT_ERROR; + fclose (temp); + } + else +#endif + if (rename (outfilename_temp, outfilename)) { + error_line ("can not rename temp file %s to %s!", outfilename_temp, outfilename); + result = SOFT_ERROR; + } + + if (out2filename) { +#if defined(WIN32) + FILE *temp; + + if (remove (out2filename) && (temp = fopen (out2filename, "rb"))) { + error_line ("can not remove file %s, result saved in %s!", out2filename, out2filename_temp); + result = SOFT_ERROR; + fclose (temp); + } + else +#endif + if (rename (out2filename_temp, out2filename)) { + error_line ("can not rename temp file %s to %s!", out2filename_temp, out2filename); + result = SOFT_ERROR; + } + } + + free (outfilename_temp); + if (out2filename) free (out2filename_temp); + + if (result != NO_ERROR) { + WavpackCloseFile (outfile); + return result; + } + } + + // compute and display the time consumed along with some other details of + // the packing operation, and then return NO_ERROR + +#if defined(WIN32) + _ftime (&time2); + dtime = time2.time + time2.millitm / 1000.0; + dtime -= time1.time + time1.millitm / 1000.0; +#else + gettimeofday(&time2,&timez); + dtime = time2.tv_sec + time2.tv_usec / 1000000.0; + dtime -= time1.tv_sec + time1.tv_usec / 1000000.0; +#endif + + if ((loc_config.flags & CONFIG_CALC_NOISE) && WavpackGetEncodedNoise (outfile, NULL) > 0.0) { + int full_scale_bits = WavpackGetBitsPerSample (outfile); + double full_scale_rms = 0.5, sum, peak; + + while (full_scale_bits--) + full_scale_rms *= 2.0; + + full_scale_rms = full_scale_rms * (full_scale_rms - 1.0) * 0.5; + sum = WavpackGetEncodedNoise (outfile, &peak); + + error_line ("ave noise = %.2f dB, peak noise = %.2f dB", + log10 (sum / WavpackGetNumSamples (outfile) / full_scale_rms) * 10, + log10 (peak / full_scale_rms) * 10); + } + + if (!quiet_mode) { + char *file, *fext, *oper, *cmode, cratio [16] = ""; + + if (config->flags & CONFIG_MD5_CHECKSUM) { + char md5_string [] = "original md5 signature: 00000000000000000000000000000000"; + int i; + + for (i = 0; i < 16; ++i) + sprintf (md5_string + 24 + (i * 2), "%02x", md5_display [i]); - if (!quiet_mode) error_line (md5_string); + } - WavpackStoreMD5Sum (wpc, md5_digest); + if (outfilename && *outfilename != '-') { + file = FN_FIT (outfilename); + fext = wvc_file.bytes_written ? " (+.wvc)" : ""; + oper = verify_mode ? "created (and verified)" : "created"; + } + else { + file = (*infilename == '-') ? "stdin" : FN_FIT (infilename); + fext = ""; + oper = "packed"; + } + + if (WavpackLossyBlocks (outfile)) { + cmode = "lossy"; + + if (WavpackGetAverageBitrate (outfile, TRUE) != 0.0) + sprintf (cratio, ", %d kbps", (int) (WavpackGetAverageBitrate (outfile, TRUE) / 1000.0)); + } + else { + cmode = "lossless"; + + if (WavpackGetRatio (outfile) != 0.0) + sprintf (cratio, ", %.2f%%", 100.0 - WavpackGetRatio (outfile) * 100.0); + } + + error_line ("%s %s%s in %.2f secs (%s%s)", oper, file, fext, dtime, cmode, cratio); + } + + WavpackCloseFile (outfile); + return NO_ERROR; +} + +// This function handles the actual audio data transcoding. It assumes that the +// input file is positioned at the beginning of the audio data and that the +// WavPack configuration has been set. If the "md5_digest_source" pointer is not +// NULL, then a MD5 sum is calculated on the audio data during the transcoding +// and stored there at the completion. Note that the md5 requires a conversion +// to the native data format (endianness and bytes per sample) that is not +// required overwise. + +static unsigned char *format_samples (int bps, unsigned char *dst, int32_t *src, uint32_t samcnt); + +static int repack_audio (WavpackContext *outfile, WavpackContext *infile, unsigned char *md5_digest_source) +{ + int bps = WavpackGetBytesPerSample (infile), num_channels = WavpackGetNumChannels (infile); + uint32_t input_samples = INPUT_SAMPLES, samples_read = 0; + unsigned char *format_buffer; + int32_t *sample_buffer; + double progress = -1.0; + MD5_CTX md5_context; + + // don't use an absurd amount of memory just because we have an absurd number of channels + + while (input_samples * sizeof (int32_t) * WavpackGetNumChannels (outfile) > 2048*1024) + input_samples >>= 1; + + if (md5_digest_source) { + format_buffer = malloc (input_samples * bps * WavpackGetNumChannels (outfile)); + MD5Init (&md5_context); + } + + WavpackPackInit (outfile); + sample_buffer = malloc (input_samples * sizeof (int32_t) * WavpackGetNumChannels (outfile)); + + while (1) { + unsigned int sample_count = WavpackUnpackSamples (infile, sample_buffer, input_samples); + + if (!sample_count) + break; + + if (md5_digest_source) { + format_samples (bps, format_buffer, sample_buffer, sample_count * num_channels); + MD5Update (&md5_context, format_buffer, bps * sample_count * num_channels); + } + + if (!WavpackPackSamples (outfile, sample_buffer, sample_count)) { + error_line ("%s", WavpackGetErrorMessage (outfile)); + free (sample_buffer); + return HARD_ERROR; + } + + if (check_break ()) { +#if defined(WIN32) + fprintf (stderr, "^C\n"); +#else + fprintf (stderr, "\n"); +#endif + free (sample_buffer); + return SOFT_ERROR; + } + + if (WavpackGetProgress (outfile) != -1.0 && + progress != floor (WavpackGetProgress (outfile) * encode_time_percent + 0.5)) { + int nobs = progress == -1.0; + + progress = floor (WavpackGetProgress (outfile) * encode_time_percent + 0.5); + display_progress (progress / 100.0); + + if (!quiet_mode) + fprintf (stderr, "%s%3d%% done...", + nobs ? " " : "\b\b\b\b\b\b\b\b\b\b\b\b", (int) progress); + } + } + + free (sample_buffer); + + if (!WavpackFlushSamples (outfile)) { + error_line ("%s", WavpackGetErrorMessage (outfile)); + return HARD_ERROR; + } + + if (md5_digest_source) { + MD5Final (md5_digest_source, &md5_context); + free (format_buffer); } return NO_ERROR; @@ -2060,6 +2923,183 @@ static void reorder_channels (void *data, unsigned char *order, int num_chans, free (temp); } +// Verify the specified WavPack input file. This function uses the library +// routines provided in wputils.c to do all unpacking. If an MD5 sum is provided +// by the caller, then this function will take care of reformatting the data +// (which is returned in native-endian longs) to the standard little-endian +// for a proper MD5 verification. Otherwise a lossy verification is assumed, +// and we only verify the exact number of samples and whether the decoding +// library detected CRC errors in any WavPack blocks. + +static int verify_audio (char *infilename, unsigned char *md5_digest_source) +{ + int bytes_per_sample, num_channels, wvc_mode, bps; + uint32_t total_unpacked_samples = 0; + unsigned char md5_digest_result [16]; + double progress = -1.0; + int result = NO_ERROR; + int32_t *temp_buffer; + MD5_CTX md5_context; + WavpackContext *wpc; + char error [80]; + + // use library to open WavPack file + + wpc = WavpackOpenFileInput (infilename, error, OPEN_WVC, 0); + + if (!wpc) { + error_line (error); + return SOFT_ERROR; + } + + if (md5_digest_source) + MD5Init (&md5_context); + + wvc_mode = WavpackGetMode (wpc) & MODE_WVC; + num_channels = WavpackGetNumChannels (wpc); + bps = WavpackGetBytesPerSample (wpc); + bytes_per_sample = num_channels * bps; + temp_buffer = malloc (4096L * num_channels * 4); + + while (result == NO_ERROR) { + uint32_t samples_unpacked; + + samples_unpacked = WavpackUnpackSamples (wpc, temp_buffer, 4096); + total_unpacked_samples += samples_unpacked; + + if (md5_digest_source && samples_unpacked) { + format_samples (bps, (unsigned char *) temp_buffer, temp_buffer, samples_unpacked * num_channels); + MD5Update (&md5_context, (unsigned char *) temp_buffer, bps * samples_unpacked * num_channels); + } + + if (!samples_unpacked) + break; + + if (check_break ()) { +#if defined(WIN32) + fprintf (stderr, "^C\n"); +#else + fprintf (stderr, "\n"); +#endif + result = SOFT_ERROR; + break; + } + + if (WavpackGetProgress (wpc) != -1.0 && + progress != floor (WavpackGetProgress (wpc) * (100.0 - encode_time_percent) + encode_time_percent + 0.5)) { + + progress = floor (WavpackGetProgress (wpc) * (100.0 - encode_time_percent) + encode_time_percent + 0.5); + display_progress (progress / 100.0); + + if (!quiet_mode) + fprintf (stderr, "%s%3d%% done...", + "\b\b\b\b\b\b\b\b\b\b\b\b", (int) progress); + } + } + + free (temp_buffer); + + // If we have been provided an MD5 sum, then the assumption is that we are doing lossless compression (either explicitly + // with lossless mode or having a high enough bitrate that the result is lossless) and we can use the MD5 sum as a pretty + // definitive verification. + + if (result == NO_ERROR && md5_digest_source) { + MD5Final (md5_digest_result, &md5_context); + + if (memcmp (md5_digest_result, md5_digest_source, 16)) { + char md5_string1 [] = "00000000000000000000000000000000"; + char md5_string2 [] = "00000000000000000000000000000000"; + int i; + + for (i = 0; i < 16; ++i) { + sprintf (md5_string1 + (i * 2), "%02x", md5_digest_source [i]); + sprintf (md5_string2 + (i * 2), "%02x", md5_digest_result [i]); + } + + error_line ("original md5: %s", md5_string1); + error_line ("verified md5: %s", md5_string2); + error_line ("MD5 signatures should match, but do not!"); + result = SOFT_ERROR; + } + } + + // If we have not been provided an MD5 sum, then the assumption is that we are doing lossy compression and cannot rely + // (obviously) on that for verification. For these cases we make sure that the number of samples generated was exactly + // correct and that the WavPack decoding library did not detect an error. There is a simple CRC on every WavPack block + // that should catch any random corruption, although it's possible that this might miss some decoder bug that occurs + // late in the decoding process (e.g., after the CRC). + + if (result == NO_ERROR) { + if (WavpackGetNumSamples (wpc) != (uint32_t) -1) { + if (total_unpacked_samples < WavpackGetNumSamples (wpc)) { + error_line ("file is missing %u samples!", + WavpackGetNumSamples (wpc) - total_unpacked_samples); + result = SOFT_ERROR; + } + else if (total_unpacked_samples > WavpackGetNumSamples (wpc)) { + error_line ("file has %u extra samples!", + total_unpacked_samples - WavpackGetNumSamples (wpc)); + result = SOFT_ERROR; + } + } + + if (WavpackGetNumErrors (wpc)) { + error_line ("missing data or crc errors detected in %d block(s)!", WavpackGetNumErrors (wpc)); + result = SOFT_ERROR; + } + } + + WavpackCloseFile (wpc); + return result; +} + +// Reformat samples from longs in processor's native endian mode to +// little-endian data with (possibly) less than 4 bytes / sample. + +static unsigned char *format_samples (int bps, unsigned char *dst, int32_t *src, uint32_t samcnt) +{ + int32_t temp; + + switch (bps) { + + case 1: + while (samcnt--) + *dst++ = *src++ + 128; + + break; + + case 2: + while (samcnt--) { + *dst++ = (unsigned char) (temp = *src++); + *dst++ = (unsigned char) (temp >> 8); + } + + break; + + case 3: + while (samcnt--) { + *dst++ = (unsigned char) (temp = *src++); + *dst++ = (unsigned char) (temp >> 8); + *dst++ = (unsigned char) (temp >> 16); + } + + break; + + case 4: + while (samcnt--) { + *dst++ = (unsigned char) (temp = *src++); + *dst++ = (unsigned char) (temp >> 8); + *dst++ = (unsigned char) (temp >> 16); + *dst++ = (unsigned char) (temp >> 24); + } + + break; + } + + return dst; +} +#if defined(WIN32) + // Convert the Unicode wide-format string into a UTF-8 string using no more // than the specified buffer length. The wide-format string must be NULL // terminated and the resulting string will be NULL terminated. The actual @@ -2067,11 +3107,9 @@ static void reorder_channels (void *data, unsigned char *order, int num_chans, // may be less than the number of characters in the wide string if the buffer // length is exceeded. -#if defined(WIN32) - -static int WideCharToUTF8 (const unsigned short *Wide, unsigned char *pUTF8, int len) +static int WideCharToUTF8 (const wchar_t *Wide, unsigned char *pUTF8, int len) { - const unsigned short *pWide = Wide; + const wchar_t *pWide = Wide; int outndx = 0; while (*pWide) { @@ -2094,27 +3132,38 @@ static int WideCharToUTF8 (const unsigned short *Wide, unsigned char *pUTF8, int return (int)(pWide - Wide); } -#endif - -// Convert a Ansi string into its Unicode UTF-8 format equivalent. The +// Convert a text string into its Unicode UTF-8 format equivalent. The // conversion is done in-place so the maximum length of the string buffer must // be specified because the string may become longer or shorter. If the // resulting string will not fit in the specified buffer size then it is // truncated. -static void AnsiToUTF8 (char *string, int len) +static void TextToUTF8 (void *string, int len) { - int max_chars = (int) strlen (string); -#if defined(WIN32) - unsigned short *temp = (unsigned short *) malloc ((max_chars + 1) * 2); + if (* (wchar_t *) string == 0xFEFF) { + wchar_t *temp = _wcsdup (string); + + WideCharToUTF8 (temp + 1, (unsigned char *) string, len); + free (temp); + } + else { + int max_chars = (int) strlen (string); + wchar_t *temp = (wchar_t *) malloc ((max_chars + 1) * 2); + + MultiByteToWideChar (CP_ACP, 0, string, -1, temp, max_chars + 1); + WideCharToUTF8 (temp, (unsigned char *) string, len); + free (temp); + } +} - MultiByteToWideChar (CP_ACP, 0, string, -1, temp, max_chars + 1); - WideCharToUTF8 (temp, (unsigned char *) string, len); #else + +static void TextToUTF8 (void *string, int len) +{ char *temp = malloc (len); char *outp = temp; char *inp = string; - size_t insize = max_chars; + size_t insize = 0; size_t outsize = len - 1; int err = 0; char *old_locale; @@ -2122,7 +3171,19 @@ static void AnsiToUTF8 (char *string, int len) memset(temp, 0, len); old_locale = setlocale (LC_CTYPE, ""); - converter = iconv_open ("UTF-8", ""); + + if ((unsigned char) inp [0] == 0xFF && (unsigned char) inp [1] == 0xFE) { + uint16_t *utf16p = (uint16_t *) (inp += 2); + + while (*utf16p++) + insize += 2; + + converter = iconv_open ("UTF-8", "UTF-16LE"); + } + else { + insize = strlen (string); + converter = iconv_open ("UTF-8", ""); + } if (converter != (iconv_t) -1) { err = iconv (converter, &inp, &insize, &outp, &outsize); @@ -2139,10 +3200,11 @@ static void AnsiToUTF8 (char *string, int len) } memmove (string, temp, len); -#endif free (temp); } +#endif + ////////////////////////////////////////////////////////////////////////////// // This function displays the progress status on the title bar of the DOS // // window that WavPack is running in. The "file_progress" argument is for // @@ -2154,9 +3216,9 @@ static void display_progress (double file_progress) { char title [40]; - file_progress = (file_index + file_progress) / num_files; - sprintf (title, "%d%% (WavPack)", (int) ((file_progress * 100.0) + 0.5)); -#if defined(WIN32) - SetConsoleTitle (title); -#endif + if (!no_console_title) { + file_progress = (file_index + file_progress) / num_files; + sprintf (title, "%d%% (WavPack)", (int) ((file_progress * 100.0) + 0.5)); + DoSetConsoleTitle (title); + } } diff --git a/Frameworks/WavPack/Files/wavpack.pc.in b/Frameworks/WavPack/Files/wavpack.pc.in deleted file mode 100644 index 553127ed7..000000000 --- a/Frameworks/WavPack/Files/wavpack.pc.in +++ /dev/null @@ -1,11 +0,0 @@ -prefix=@prefix@ -libdir=${prefix}/lib -includedir=${prefix}/include - -Name: wavpack -Description: wavpack library -Version: @PACKAGE_VERSION@ -Requires: -Conflicts: -Libs: -L${libdir} -lwavpack @ICONV@ -Cflags: -I${includedir} -DPACK -DUNPACK -DUSE_FSTREAMS -DTAGS -DSEEKING -DVER3 diff --git a/Frameworks/WavPack/Files/wavpack_local.h b/Frameworks/WavPack/Files/wavpack_local.h index 9f3ec37cd..5c69108e1 100644 --- a/Frameworks/WavPack/Files/wavpack_local.h +++ b/Frameworks/WavPack/Files/wavpack_local.h @@ -11,6 +11,10 @@ #ifndef WAVPACK_LOCAL_H #define WAVPACK_LOCAL_H +#ifndef __has_builtin +#define __has_builtin(x) 0 +#endif + #if defined(WIN32) #define FASTCALL __fastcall #else @@ -85,10 +89,10 @@ typedef struct { #define APE_TAG_TYPE_BINARY 0x1 #define APE_TAG_THIS_IS_HEADER 0x20000000 #define APE_TAG_CONTAINS_HEADER 0x80000000 -#define APE_TAG_MAX_LENGTH (1024 * 1024) +#define APE_TAG_MAX_LENGTH (1024 * 1024 * 16) typedef struct { - int32_t tag_file_pos; + int32_t tag_file_pos, tag_begins_file; ID3_Tag id3_tag; APE_Tag_Hdr ape_tag_hdr; unsigned char *ape_tag_data; @@ -324,7 +328,7 @@ struct decorr_pass { }; typedef struct { - char joint_stereo, delta, terms [MAX_NTERMS+1]; + signed char joint_stereo, delta, terms [MAX_NTERMS+1]; } WavpackDecorrSpec; struct entropy_data { @@ -510,7 +514,7 @@ int DoCloseHandle (FILE *hFile), DoTruncateFile (FILE *hFile); ((bs)->sr >>= 1, 0) \ ) -#define getbits(value, nbits, bs) { \ +#define getbits(value, nbits, bs) do { \ while ((nbits) > (bs)->bc) { \ if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ (bs)->sr |= (int32_t)*((bs)->ptr) << (bs)->bc; \ @@ -525,30 +529,30 @@ int DoCloseHandle (FILE *hFile), DoTruncateFile (FILE *hFile); (bs)->bc -= (nbits); \ (bs)->sr >>= (nbits); \ } \ -} +} while (0) -#define putbit(bit, bs) { if (bit) (bs)->sr |= (1 << (bs)->bc); \ +#define putbit(bit, bs) do { if (bit) (bs)->sr |= (1 << (bs)->bc); \ if (++((bs)->bc) == sizeof (*((bs)->ptr)) * 8) { \ *((bs)->ptr) = (bs)->sr; \ (bs)->sr = (bs)->bc = 0; \ if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ - }} + }} while (0) -#define putbit_0(bs) { \ +#define putbit_0(bs) do { \ if (++((bs)->bc) == sizeof (*((bs)->ptr)) * 8) { \ *((bs)->ptr) = (bs)->sr; \ (bs)->sr = (bs)->bc = 0; \ if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ - }} + }} while (0) -#define putbit_1(bs) { (bs)->sr |= (1 << (bs)->bc); \ +#define putbit_1(bs) do { (bs)->sr |= (1 << (bs)->bc); \ if (++((bs)->bc) == sizeof (*((bs)->ptr)) * 8) { \ *((bs)->ptr) = (bs)->sr; \ (bs)->sr = (bs)->bc = 0; \ if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ - }} + }} while (0) -#define putbits(value, nbits, bs) { \ +#define putbits(value, nbits, bs) do { \ (bs)->sr |= (int32_t)(value) << (bs)->bc; \ if (((bs)->bc += (nbits)) >= sizeof (*((bs)->ptr)) * 8) \ do { \ @@ -558,7 +562,7 @@ int DoCloseHandle (FILE *hFile), DoTruncateFile (FILE *hFile); (bs)->sr |= ((value) >> ((nbits) - (bs)->bc)); \ if (++((bs)->ptr) == (bs)->end) (bs)->wrap (bs); \ } while ((bs)->bc >= sizeof (*((bs)->ptr)) * 8); \ -} +} while (0) void little_endian_to_native (void *data, char *format); void native_to_little_endian (void *data, char *format); @@ -736,6 +740,7 @@ int WavpackWriteTag (WavpackContext *wpc); int load_tag (WavpackContext *wpc); void free_tag (M_Tag *m_tag); int valid_tag (M_Tag *m_tag); +int editable_tag (M_Tag *m_tag); ///////////////////////////// SIMD helper macros ///////////////////////////// @@ -768,7 +773,7 @@ typedef short __m64_16 __attribute__ ((__vector_size__ (8))); #define _m_paddd(m1, m2) __builtin_ia32_paddd (m1, m2) #define _m_pcmpeqd(m1, m2) __builtin_ia32_pcmpeqd (m1, m2) -#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __GNUC__ > 4 +#if (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) || __GNUC__ > 4 || __has_builtin(__builtin_ia32_pslldi) # define _m_pslldi(m1, m2) __builtin_ia32_pslldi ((__m64)m1, m2) # define _m_psradi(m1, m2) __builtin_ia32_psradi ((__m64)m1, m2) # define _m_psrldi(m1, m2) __builtin_ia32_psrldi ((__m64)m1, m2) diff --git a/Frameworks/WavPack/Files/wavpack_version.h b/Frameworks/WavPack/Files/wavpack_version.h index 6d5aad3c8..ed6e241dd 100644 --- a/Frameworks/WavPack/Files/wavpack_version.h +++ b/Frameworks/WavPack/Files/wavpack_version.h @@ -12,8 +12,8 @@ #define WAVPACK_VERSION_H #define LIBWAVPACK_MAJOR 4 -#define LIBWAVPACK_MINOR 60 -#define LIBWAVPACK_MICRO 1 -#define LIBWAVPACK_VERSION_STRING "4.60.1" +#define LIBWAVPACK_MINOR 70 +#define LIBWAVPACK_MICRO 0 +#define LIBWAVPACK_VERSION_STRING "4.70.0" #endif diff --git a/Frameworks/WavPack/Files/words.c b/Frameworks/WavPack/Files/words.c index c87b8d2d9..368b07aed 100644 --- a/Frameworks/WavPack/Files/words.c +++ b/Frameworks/WavPack/Files/words.c @@ -3,6 +3,7 @@ // Hybrid Lossless Wavefile Compressor // // Copyright (c) 1998 - 2006 Conifer Software. // // All Rights Reserved. // +// Distributed under the BSD Software License (see license.txt) // //////////////////////////////////////////////////////////////////////////// // words.c @@ -40,6 +41,8 @@ int32_t dump_alloc (void); //////////////////////////////// local macros ///////////////////////////////// +#define USE_NEXT8_OPTIMIZATION // we normally want this, but code is easier to understand without it + #define LIMIT_ONES 16 // maximum consecutive 1s sent for "div" data // these control the time constant "slow_level" which is used for hybrid mode @@ -156,6 +159,7 @@ static const unsigned char exp2_table [] = { 0xea, 0xec, 0xed, 0xee, 0xf0, 0xf1, 0xf2, 0xf4, 0xf5, 0xf6, 0xf8, 0xf9, 0xfa, 0xfc, 0xfd, 0xff }; +#ifdef USE_NEXT8_OPTIMIZATION static const char ones_count_table [] = { 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,6, @@ -166,6 +170,7 @@ static const char ones_count_table [] = { 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,5, 0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,8 }; +#endif ///////////////////////////// executable code //////////////////////////////// @@ -482,9 +487,8 @@ int32_t FASTCALL send_word (WavpackStream *wps, int32_t value, int chan) return 0; } } - else if (value) { + else if (value) putbit_0 (&wps->wvbits); - } else { c->slow_level -= (c->slow_level + SLO) >> SLS; CLEAR (wps->w.c [0].median); @@ -593,9 +597,8 @@ int32_t FASTCALL send_word (WavpackStream *wps, int32_t value, int chan) uint32_t extras = bitset [bitcount] - maxcode - 1; if (bitcount) { - if (code < extras) { + if (code < extras) putbits (code, bitcount - 1, &wps->wvcbits); - } else { putbits ((code + extras) >> 1, bitcount - 1, &wps->wvcbits); putbit ((code + extras) & 1, &wps->wvcbits); @@ -641,9 +644,8 @@ void send_words_lossless (WavpackStream *wps, int32_t *buffer, int32_t nsamples) continue; } } - else if (value) { + else if (value) putbit_0 (&wps->wvbits); - } else { CLEAR (wps->w.c [0].median); CLEAR (wps->w.c [1].median); @@ -737,9 +739,8 @@ void flush_word (WavpackStream *wps) if (wps->w.zeros_acc) { int cbits = count_bits (wps->w.zeros_acc); - while (cbits--) { + while (cbits--) putbit_1 (&wps->wvbits); - } putbit_0 (&wps->wvbits); @@ -760,9 +761,8 @@ void flush_word (WavpackStream *wps) wps->w.holding_one -= LIMIT_ONES; cbits = count_bits (wps->w.holding_one); - while (cbits--) { + while (cbits--) putbit_1 (&wps->wvbits); - } putbit_0 (&wps->wvbits); @@ -1025,6 +1025,7 @@ int32_t FASTCALL get_word (WavpackStream *wps, int chan, int32_t *correction) if (wps->w.holding_zero) ones_count = wps->w.holding_zero = 0; else { +#ifdef USE_NEXT8_OPTIMIZATION if (wps->wvbits.bc < 8) { if (++(wps->wvbits.ptr) == wps->wvbits.end) wps->wvbits.wrap (&wps->wvbits); @@ -1070,6 +1071,34 @@ int32_t FASTCALL get_word (WavpackStream *wps, int chan, int32_t *correction) wps->wvbits.bc -= (ones_count = ones_count_table [next8]) + 1; wps->wvbits.sr >>= ones_count + 1; } +#else + for (ones_count = 0; ones_count < (LIMIT_ONES + 1) && getbit (&wps->wvbits); ++ones_count); + + if (ones_count >= LIMIT_ONES) { + uint32_t mask; + int cbits; + + if (ones_count == (LIMIT_ONES + 1)) + return WORD_EOF; + + for (cbits = 0; cbits < 33 && getbit (&wps->wvbits); ++cbits); + + if (cbits == 33) + return WORD_EOF; + + if (cbits < 2) + ones_count = cbits; + else { + for (mask = 1, ones_count = 0; --cbits; mask <<= 1) + if (getbit (&wps->wvbits)) + ones_count |= mask; + + ones_count |= mask; + } + + ones_count += LIMIT_ONES; + } +#endif if (wps->w.holding_one) { wps->w.holding_one = ones_count & 1; @@ -1201,6 +1230,7 @@ int32_t get_words_lossless (WavpackStream *wps, int32_t *buffer, int32_t nsample if (wps->w.holding_zero) ones_count = wps->w.holding_zero = 0; else { +#ifdef USE_NEXT8_OPTIMIZATION int next8; if (bs->bc < 8) { @@ -1248,7 +1278,34 @@ int32_t get_words_lossless (WavpackStream *wps, int32_t *buffer, int32_t nsample bs->bc -= (ones_count = ones_count_table [next8]) + 1; bs->sr >>= ones_count + 1; } +#else + for (ones_count = 0; ones_count < (LIMIT_ONES + 1) && getbit (bs); ++ones_count); + if (ones_count >= LIMIT_ONES) { + uint32_t mask; + int cbits; + + if (ones_count == (LIMIT_ONES + 1)) + break; + + for (cbits = 0; cbits < 33 && getbit (bs); ++cbits); + + if (cbits == 33) + break; + + if (cbits < 2) + ones_count = cbits; + else { + for (mask = 1, ones_count = 0; --cbits; mask <<= 1) + if (getbit (bs)) + ones_count |= mask; + + ones_count |= mask; + } + + ones_count += LIMIT_ONES; + } +#endif if (wps->w.holding_one) { wps->w.holding_one = ones_count & 1; ones_count = (ones_count >> 1) + 1; diff --git a/Frameworks/WavPack/Files/wputils.c b/Frameworks/WavPack/Files/wputils.c index 3303d6fce..5d30f1e2d 100644 --- a/Frameworks/WavPack/Files/wputils.c +++ b/Frameworks/WavPack/Files/wputils.c @@ -38,7 +38,7 @@ #define stricmp(x,y) _stricmp(x,y) #define fileno _fileno #else -#define stricmp(x,y) strcasecmp(x,y) +#define stricmp strcasecmp #endif #ifdef DEBUG_ALLOC @@ -170,7 +170,7 @@ WavpackContext *WavpackOpenFileInput (const char *infilename, char *error, int f #endif } else if ((wv_id = fopen (infilename, file_mode)) == NULL) { - strcpy (error, (flags & OPEN_EDIT_TAGS) ? "can't open file for editing" : "can't open file"); + if (error) strcpy (error, (flags & OPEN_EDIT_TAGS) ? "can't open file for editing" : "can't open file"); return NULL; } @@ -219,7 +219,7 @@ WavpackContext *WavpackOpenFileInputEx (WavpackStreamReader *reader, void *wv_id uint32_t bcount; if (!wpc) { - strcpy (error, "can't allocate memory"); + if (error) strcpy (error, "can't allocate memory"); return NULL; } @@ -238,12 +238,17 @@ WavpackContext *WavpackOpenFileInputEx (WavpackStreamReader *reader, void *wv_id if ((flags & (OPEN_TAGS | OPEN_EDIT_TAGS)) && wpc->reader->can_seek (wpc->wv_in)) { load_tag (wpc); wpc->reader->set_pos_abs (wpc->wv_in, 0); + + if ((flags & OPEN_EDIT_TAGS) && !editable_tag (&wpc->m_tag)) { + if (error) strcpy (error, "can't edit tags located at the beginning of files!"); + return WavpackCloseFile (wpc); + } } #endif #ifndef VER4_ONLY if (wpc->reader->read_bytes (wpc->wv_in, &first_byte, 1) != 1) { - strcpy (error, "can't read all of WavPack file!"); + if (error) strcpy (error, "can't read all of WavPack file!"); return WavpackCloseFile (wpc); } @@ -264,7 +269,7 @@ WavpackContext *WavpackOpenFileInputEx (WavpackStreamReader *reader, void *wv_id if (bcount == (uint32_t) -1 || (!wps->wphdr.block_samples && num_blocks++ > 16)) { - strcpy (error, "not compatible with this version of WavPack file!"); + if (error) strcpy (error, "not compatible with this version of WavPack file!"); return WavpackCloseFile (wpc); } @@ -273,7 +278,7 @@ WavpackContext *WavpackOpenFileInputEx (WavpackStreamReader *reader, void *wv_id memcpy (wps->blockbuff, &wps->wphdr, 32); if (wpc->reader->read_bytes (wpc->wv_in, wps->blockbuff + 32, wps->wphdr.ckSize - 24) != wps->wphdr.ckSize - 24) { - strcpy (error, "can't read all of WavPack file!"); + if (error) strcpy (error, "can't read all of WavPack file!"); return WavpackCloseFile (wpc); } @@ -304,12 +309,12 @@ WavpackContext *WavpackOpenFileInputEx (WavpackStreamReader *reader, void *wv_id } if (wpc->wvc_flag && !read_wvc_block (wpc)) { - strcpy (error, "not compatible with this version of correction file!"); + if (error) strcpy (error, "not compatible with this version of correction file!"); return WavpackCloseFile (wpc); } if (!wps->init_done && !unpack_init (wpc)) { - strcpy (error, wpc->error_message [0] ? wpc->error_message : + if (error) strcpy (error, wpc->error_message [0] ? wpc->error_message : "not compatible with this version of WavPack file!"); return WavpackCloseFile (wpc); @@ -327,7 +332,7 @@ WavpackContext *WavpackOpenFileInputEx (WavpackStreamReader *reader, void *wv_id ((wps->wphdr.flags & SHIFT_MASK) >> SHIFT_LSB); if (!wpc->config.sample_rate) { - if (!wps || !wps->wphdr.block_samples || (wps->wphdr.flags & SRATE_MASK) == SRATE_MASK) + if (!wps->wphdr.block_samples || (wps->wphdr.flags & SRATE_MASK) == SRATE_MASK) wpc->config.sample_rate = 44100; else wpc->config.sample_rate = sample_rates [(wps->wphdr.flags & SRATE_MASK) >> SRATE_LSB]; @@ -478,16 +483,20 @@ uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t sa if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) || wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples) { + uint32_t nexthdrpos; + if (wpc->wrapper_bytes >= MAX_WRAPPER_BYTES) break; free_streams (wpc); - wpc->filepos = wpc->reader->get_pos (wpc->wv_in); + nexthdrpos = wpc->reader->get_pos (wpc->wv_in); bcount = read_next_header (wpc->reader, wpc->wv_in, &wps->wphdr); if (bcount == (uint32_t) -1) break; + wpc->filepos = nexthdrpos; + if (wpc->open_flags & OPEN_STREAMING) wps->wphdr.block_index = wps->sample_index = 0; else @@ -1396,7 +1405,7 @@ static int pack_streams (WavpackContext *wpc, uint32_t block_samples) } if (wpc->acc_samples != block_samples) - memcpy (wps->sample_buffer, wps->sample_buffer + block_samples * (flags & MONO_FLAG ? 1 : 2), + memmove (wps->sample_buffer, wps->sample_buffer + block_samples * (flags & MONO_FLAG ? 1 : 2), (wpc->acc_samples - block_samples) * sizeof (int32_t) * (flags & MONO_FLAG ? 1 : 2)); } @@ -2233,7 +2242,7 @@ static uint32_t find_header (WavpackStreamReader *reader, void *id, uint32_t fil if (wphdr->block_samples && (wphdr->flags & INITIAL_BLOCK)) { free (buffer); - return reader->get_pos (id) - (ep - sp + 4); + return (uint32_t) (reader->get_pos (id) - (ep - sp + 4)); } if (wphdr->ckSize > 1024) diff --git a/Frameworks/WavPack/Files/wvunpack.c b/Frameworks/WavPack/Files/wvunpack.c index af4569d89..424514f0b 100644 --- a/Frameworks/WavPack/Files/wvunpack.c +++ b/Frameworks/WavPack/Files/wvunpack.c @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////////////////////// // **** WAVPACK **** // // Hybrid Lossless Wavefile Compressor // -// Copyright (c) 1998 - 2009 Conifer Software. // +// Copyright (c) 1998 - 2013 Conifer Software. // // All Rights Reserved. // // Distributed under the BSD Software License (see license.txt) // //////////////////////////////////////////////////////////////////////////// @@ -11,6 +11,7 @@ // This is the main module for the WavPack command-line decompressor. #if defined(WIN32) +#define WIN32_LEAN_AND_MEAN #include #include #else @@ -67,32 +68,35 @@ static char *strdup (const char *s) static const char *sign_on = "\n" " WVUNPACK Hybrid Lossless Audio Decompressor %s Version %s\n" -" Copyright (c) 1998 - 2009 Conifer Software. All Rights Reserved.\n\n"; +" Copyright (c) 1998 - 2013 Conifer Software. All Rights Reserved.\n\n"; static const char *usage = #if defined (WIN32) -" Usage: WVUNPACK [-options] [@]infile[.wv]|- [[@]outfile[.wav]|outpath|-]\n" -#else -" Usage: WVUNPACK [-options] [@]infile[.wv]|- [...] [-o [@]outfile[.wav]|outpath|-]\n" -#endif +" Usage: WVUNPACK [-options] infile[.wv]|- [outfile[.wav]|outpath|-]\n" " (infile may contain wildcards: ?,*)\n\n" +#else +" Usage: WVUNPACK [-options] infile[.wv]|- [...] [-o outfile[.wav]|outpath|-]\n" +#endif +" (multiple input files are allowed)\n\n" " Options: -b = blindly decode all stream blocks & ignore length info\n" " -c = extract cuesheet only to stdout (no audio decode)\n" " (note: equivalent to -x \"cuesheet\")\n" " -cc = extract cuesheet file (.cue) in addition to audio file\n" " (note: equivalent to -xx \"cuesheet=%a.cue\")\n" " -d = delete source file if successful (use with caution!)\n" +" -f = file info to stdout in machine-parsable format\n" " --help = this help display\n" " -i = ignore .wvc file (forces hybrid lossy decompression)\n" #if defined (WIN32) || defined (__OS2__) " -l = run at low priority (for smoother multitasking)\n" #endif " -m = calculate and display MD5 signature; verify if lossless\n" +" -n = no audio decoding (use with -xx to extract tags only)\n" " --no-utf8-convert = leave tag items in UTF-8 on extract or display\n" -" -q = quiet (keep console output to a minimum)\n" #if !defined (WIN32) " -o FILENAME | PATH = specify output filename or path\n" #endif +" -q = quiet (keep console output to a minimum)\n" " -r = force raw audio decode (results in .raw extension)\n" " -s = display summary information only to stdout (no audio decode)\n" " -ss = display super summary (including tags) to stdout (no decode)\n" @@ -102,6 +106,7 @@ static const char *usage = " (specifying a '+' causes sample/time to be relative to '--skip' point;\n" " specifying a '-' causes sample/time to be relative to end of file)\n" " -v = verify source data only (no output file created)\n" +" --version = write the version to stdout\n" " -w = regenerate .wav header (ignore RIFF data in file)\n" " -x \"Field\" = extract specified tag field only to stdout (no audio decode)\n" " -xx \"Field[=file]\" = extract specified tag field to file, optional\n" @@ -109,7 +114,8 @@ static const char *usage = " %a = audio output filename\n" " %t = tag field name (note: comes from data for binary tags)\n" " %e = extension from binary tag source file, or 'txt' for text tag\n" -" -y = yes to overwrite warning (use with caution!)\n\n" +" -y = yes to overwrite warning (use with caution!)\n" +" -z = don't set console title to indicate progress\n\n" " Web: Visit www.wavpack.com for latest version and info\n"; // this global is used to indicate the special "debug" mode where extra debug messages @@ -117,8 +123,8 @@ static const char *usage = int debug_logging_mode; -static char overwrite_all, delete_source, raw_decode, no_utf8_convert, - summary, ignore_wvc, quiet_mode, calc_md5, copy_time, blind_decode, wav_decode; +static char overwrite_all, delete_source, raw_decode, no_utf8_convert, no_audio_decode, file_info, + summary, ignore_wvc, quiet_mode, calc_md5, copy_time, blind_decode, wav_decode, no_console_title; static int num_files, file_index, outbuf_k; @@ -151,7 +157,7 @@ int main (argc, argv) int argc; char **argv; #ifdef __EMX__ /* OS/2 */ _wildcard (&argc, &argv); #endif - int verify_only = 0, error_count = 0, add_extension = 0, output_spec = 0, ask_help = 0, c_count = 0, x_count = 0; + int verify_only = 0, error_count = 0, add_extension = 0, output_spec = 0, c_count = 0, x_count = 0; char outpath, **matches = NULL, *outfilename = NULL; int result; @@ -192,8 +198,15 @@ int main (argc, argv) int argc; char **argv; if (*long_param++ == '=') break; - if (!strcmp (long_option, "help")) // --help - ask_help = 1; + if (!strcmp (long_option, "help")) { // --help + printf ("%s", usage); + return 1; + } + else if (!strcmp (long_option, "version")) { // --version + printf ("wvunpack %s\n", PACKAGE_VERSION); + printf ("libwavpack %s\n", WavpackGetLibraryVersionString ()); + return 1; + } else if (!strcmp (long_option, "no-utf8-convert")) // --no-utf8-convert no_utf8_convert = 1; else if (!strncmp (long_option, "skip", 4)) { // --skip @@ -265,12 +278,21 @@ int main (argc, argv) int argc; char **argv; verify_only = 1; break; + case 'F': case 'f': + file_info = quiet_mode = no_audio_decode = 1; + break; + case 'S': case 's': + no_audio_decode = 1; ++summary; break; case 'K': case 'k': outbuf_k = strtol (++*argv, argv, 10); + + if (outbuf_k < 1 || outbuf_k > 16384) // range-check for reasonable values + outbuf_k = 0; + --*argv; break; @@ -282,6 +304,10 @@ int main (argc, argv) int argc; char **argv; blind_decode = 1; break; + case 'N': case 'n': + no_audio_decode = 1; + break; + case 'R': case 'r': raw_decode = 1; break; @@ -294,6 +320,10 @@ int main (argc, argv) int argc; char **argv; quiet_mode = 1; break; + case 'Z': case 'z': + no_console_title = 1; + break; + case 'X': case 'x': if (++x_count == 3) { error_line ("illegal option: %s !", *argv); @@ -318,8 +348,10 @@ int main (argc, argv) int argc; char **argv; error_line ("can't extract more than 1 tag item to stdout at a time!"); ++error_count; } - else + else { tag_extract_stdout = *argv; + no_audio_decode = 1; + } } else if (x_count == 2) add_tag_extraction_to_list (*argv); @@ -389,12 +421,14 @@ int main (argc, argv) int argc; char **argv; error_line ("can't extract more than 1 tag item to stdout at a time!"); error_count++; } - else + else { tag_extract_stdout = "cuesheet"; + no_audio_decode = 1; + } } - if (tag_extract_stdout && (num_tag_extractions || outfilename || verify_only || delete_source || wav_decode || raw_decode)) { - error_line ("can't extract a tag to stdout and do anything else!"); + if ((summary || tag_extract_stdout) && (num_tag_extractions || outfilename || verify_only || delete_source || wav_decode || raw_decode)) { + error_line ("can't display summary information or extract a tag to stdout and do anything else!"); ++error_count; } @@ -406,7 +440,7 @@ int main (argc, argv) int argc; char **argv; if (!quiet_mode && !error_count) fprintf (stderr, sign_on, VERSION_OS, WavpackGetLibraryVersionString ()); - if (!num_files || ask_help) { + if (!num_files) { printf ("%s", usage); return 1; } @@ -580,7 +614,7 @@ int main (argc, argv) int argc; char **argv; if (outfilename && *outfilename != '-' && add_extension) strcat (outfilename, raw_decode ? ".raw" : ".wav"); - if (num_files > 1) + if (num_files > 1 && !quiet_mode) fprintf (stderr, "\n%s:\n", matches [file_index]); result = unpack_file (matches [file_index], verify_only ? NULL : outfilename); @@ -624,6 +658,9 @@ int main (argc, argv) int argc; char **argv; error_line ("malloc_count = %d", dump_alloc ()); #endif + if (!no_console_title) + DoSetConsoleTitle ("WvUnpack Completed"); + return error_count ? 1 : 0; } @@ -667,6 +704,97 @@ static void parse_sample_time_index (struct sample_time_index *dst, char *src) dst->value_is_valid = 1; } + +// Open specified file for writing, with overwrite check. If the specified file already exists (and the user has +// agreed to overwrite) then open a temp file instead and store a pointer to that filename at "tempfilename" (otherwise +// the pointer is set to NULL). The caller will be required to perform the rename (and free the pointer) once the file +// is completely written and closed. Note that for a file to be considered "overwritable", it must both be openable for +// reading and have at least 1 readable byte - this prevents us getting stuck on "nul" (Windows). + +static FILE *open_output_file (char *filename, char **tempfilename) +{ + FILE *retval, *testfile; + char dummy; + + *tempfilename = NULL; + + if (*filename == '-') { +#if defined(WIN32) + _setmode (fileno (stdout), O_BINARY); +#endif +#if defined(__OS2__) + setmode (fileno (stdout), O_BINARY); +#endif + return stdout; + } + + testfile = fopen (filename, "rb"); + + if (testfile) { + size_t res = fread (&dummy, 1, 1, testfile); + + fclose (testfile); + + if (res == 1) { + int count = 0; + + if (!overwrite_all) { + fprintf (stderr, "overwrite %s (yes/no/all)? ", FN_FIT (filename)); + + if (!no_console_title) + DoSetConsoleTitle ("overwrite?"); + + switch (yna ()) { + case 'n': + return NULL; + + case 'a': + overwrite_all = 1; + } + } + + *tempfilename = malloc (strlen (filename) + 16); + + while (1) { + strcpy (*tempfilename, filename); + + if (filespec_ext (*tempfilename)) { + if (count++) + sprintf (filespec_ext (*tempfilename), ".tmp%d", count-1); + else + strcpy (filespec_ext (*tempfilename), ".tmp"); + + strcat (*tempfilename, filespec_ext (filename)); + } + else { + if (count++) + sprintf (*tempfilename + strlen (*tempfilename), ".tmp%d", count-1); + else + strcat (*tempfilename, ".tmp"); + } + + testfile = fopen (*tempfilename, "rb"); + + if (!testfile) + break; + + res = fread (&dummy, 1, 1, testfile); + fclose (testfile); + + if (res != 1) + break; + } + } + } + + retval = fopen (*tempfilename ? *tempfilename : filename, "w+b"); + + if (retval == NULL) + error_line ("can't create file %s!", *tempfilename ? *tempfilename : filename); + + return retval; +} + // Unpack the specified WavPack input file into the specified output file name. // This function uses the library routines provided in wputils.c to do all // unpacking. This function takes care of reformatting the data (which is @@ -680,6 +808,7 @@ static unsigned char *format_samples (int bps, unsigned char *dst, int32_t *src, static void dump_summary (WavpackContext *wpc, char *name, FILE *dst); static int write_riff_header (FILE *outfile, WavpackContext *wpc, uint32_t total_samples); static int dump_tag_item_to_file (WavpackContext *wpc, const char *tag_item, FILE *dst, char *fn); +static void dump_file_info (WavpackContext *wpc, char *name, FILE *dst); static int unpack_file (char *infilename, char *outfilename) { @@ -689,6 +818,7 @@ static int unpack_file (char *infilename, char *outfilename) uint32_t skip_sample_index = 0, until_samples_total = 0; unsigned char *output_buffer = NULL, *output_pointer = NULL; double dtime, progress = -1.0; + char *outfilename_temp; MD5_CTX md5_context; WavpackContext *wpc; int32_t *temp_buffer; @@ -784,21 +914,16 @@ static int unpack_file (char *infilename, char *outfilename) } } - if (summary) { + if (file_info) + dump_file_info (wpc, infilename, stdout); + else if (summary) dump_summary (wpc, infilename, stdout); - WavpackCloseFile (wpc); - return NO_ERROR; - } - - if (tag_extract_stdout) { + else if (tag_extract_stdout) { if (!dump_tag_item_to_file (wpc, tag_extract_stdout, stdout, NULL)) { error_line ("tag \"%s\" not found!", tag_extract_stdout); WavpackCloseFile (wpc); return SOFT_ERROR; } - - WavpackCloseFile (wpc); - return NO_ERROR; } else if (num_tag_extractions && outfilename && *outfilename != '-' && filespec_name (outfilename)) { result = do_tag_extractions (wpc, outfilename); @@ -809,57 +934,23 @@ static int unpack_file (char *infilename, char *outfilename) } } + if (no_audio_decode) { + WavpackCloseFile (wpc); + return NO_ERROR; + } + if (outfilename) { - if (*outfilename != '-') { - - // check the output file for overwrite warning required - - if (!overwrite_all && (outfile = fopen (outfilename, "rb")) != NULL) { - DoCloseHandle (outfile); - fprintf (stderr, "overwrite %s (yes/no/all)? ", FN_FIT (outfilename)); -#if defined(WIN32) - SetConsoleTitle ("overwrite?"); -#endif - switch (yna ()) { - - case 'n': - result = SOFT_ERROR; - break; - - case 'a': - overwrite_all = 1; - } - - if (result != NO_ERROR) { - WavpackCloseFile (wpc); - return result; - } - } - - // open output file for writing - - if ((outfile = fopen (outfilename, "wb")) == NULL) { - error_line ("can't create file %s!", FN_FIT (outfilename)); - WavpackCloseFile (wpc); - return SOFT_ERROR; - } - else if (!quiet_mode) - fprintf (stderr, "restoring %s,", FN_FIT (outfilename)); + if ((outfile = open_output_file (outfilename, &outfilename_temp)) == NULL) { + WavpackCloseFile (wpc); + return SOFT_ERROR; } - else { // come here to open stdout as destination - - outfile = stdout; -#if defined(WIN32) - _setmode (fileno (stdout), O_BINARY); -#endif -#if defined(__OS2__) - setmode (fileno (stdout), O_BINARY); -#endif - + else if (*outfilename == '-') { if (!quiet_mode) fprintf (stderr, "unpacking %s%s to stdout,", *infilename == '-' ? "stdin" : FN_FIT (infilename), wvc_mode ? " (+.wvc)" : ""); } + else if (!quiet_mode) + fprintf (stderr, "restoring %s,", FN_FIT (outfilename)); if (outbuf_k) output_buffer_size = outbuf_k * 1024; @@ -867,6 +958,12 @@ static int unpack_file (char *infilename, char *outfilename) output_buffer_size = 1024 * 256; output_pointer = output_buffer = malloc (output_buffer_size); + + if (!output_buffer) { + error_line ("can't allocate buffer for decoding!"); + WavpackCloseFile (wpc); + return HARD_ERROR; + } } else { // in verify only mode we don't worry about headers outfile = NULL; @@ -915,7 +1012,7 @@ static int unpack_file (char *infilename, char *outfilename) uint32_t samples_to_unpack, samples_unpacked; if (output_buffer) { - samples_to_unpack = (output_buffer_size - (output_pointer - output_buffer)) / bytes_per_sample; + samples_to_unpack = (output_buffer_size - (uint32_t)(output_pointer - output_buffer)) / bytes_per_sample; if (samples_to_unpack > 4096) samples_to_unpack = 4096; @@ -955,7 +1052,11 @@ static int unpack_file (char *infilename, char *outfilename) break; if (check_break ()) { +#if defined(WIN32) fprintf (stderr, "^C\n"); +#else + fprintf (stderr, "\n"); +#endif DoTruncateFile (outfile); result = SOFT_ERROR; break; @@ -1029,23 +1130,47 @@ static int unpack_file (char *infilename, char *outfilename) } } - // if we are not just in verify only mode, grab the size of the output - // file and close the file - - if (outfile != NULL) { - int64_t outfile_length; + // if we are not just in verify only mode, flush the output stream and if it's a real file (not stdout) + // close it and make sure it's not zero length (which means we got an error somewhere) + if (outfile) { fflush (outfile); - outfile_length = DoGetFileSize (outfile); - if (!DoCloseHandle (outfile)) { - error_line ("can't close file %s!", FN_FIT (outfilename)); + if (*outfilename != '-') { + int64_t outfile_length = DoGetFileSize (outfile); + + if (!DoCloseHandle (outfile)) { + error_line ("can't close file %s!", FN_FIT (outfilename)); + result = SOFT_ERROR; + } + + if (!outfile_length) + DoDeleteFile (outfilename_temp ? outfilename_temp : outfilename); + } + } + + // if we were writing to a temp file because the target file already existed, + // do the rename / overwrite now (and if that fails, flag the error) + +#if defined(WIN32) + if (result == NO_ERROR && outfilename && outfilename_temp) { + if (remove (outfilename)) { + error_line ("can not remove file %s, result saved in %s!", outfilename, outfilename_temp); + result = SOFT_ERROR; + } + else if (rename (outfilename_temp, outfilename)) { + error_line ("can not rename temp file %s to %s!", outfilename_temp, outfilename); result = SOFT_ERROR; } - - if (outfilename && *outfilename != '-' && !outfile_length) - DoDeleteFile (outfilename); } +#else + if (result == NO_ERROR && outfilename && outfilename_temp && rename (outfilename_temp, outfilename)) { + error_line ("can not rename temp file %s to %s!", outfilename_temp, outfilename); + result = SOFT_ERROR; + } +#endif + + if (outfilename && outfilename_temp) free (outfilename_temp); if (result == NO_ERROR && copy_time && outfilename && !copy_timestamp (infilename, outfilename)) @@ -1228,9 +1353,10 @@ static int do_tag_extractions (WavpackContext *wpc, char *outfilename) if (!overwrite_all && (outfile = fopen (full_filename, "r")) != NULL) { DoCloseHandle (outfile); fprintf (stderr, "overwrite %s (yes/no/all)? ", FN_FIT (full_filename)); -#if defined(WIN32) - SetConsoleTitle ("overwrite?"); -#endif + + if (!no_console_title) + DoSetConsoleTitle ("overwrite?"); + switch (yna ()) { case 'n': @@ -1630,6 +1756,57 @@ static void dump_summary (WavpackContext *wpc, char *name, FILE *dst) } } +// Dump a summary of the file information in a machine-parsable format to the specified file (usually stdout). +// The items are separated by semi-colons and the line is newline terminated, like in this example: +// +// 44100;16;int;2;0x3;9878400;023066a6345773674c0755ee6be54d87;4;0x18a2;Track01.wv +// +// The fields are, in order: +// +// 1. sampling rate +// 2. bit-depth (1-32) +// 3. format ("int" or "float") +// 4. number of channels +// 5. channel mask (in hex because it's a mask, always prefixed with "0x") +// 6. number of samples (missing if unknown) +// 7. md5sum (technically is hex, but not prefixed with "0x", might be missing) +// 8. encoder version (basically this will always be 4, but there are some old files out there, could be 5 one day) +// 9. encoding mode (in hex because it's a bitfield, always prefixed with "0x") +// 10. filename (if available) + +static void dump_file_info (WavpackContext *wpc, char *name, FILE *dst) +{ + unsigned char md5_sum [16]; + char str [80]; + + sprintf (str, "%d;%d;%s;%d;0x%x;", WavpackGetSampleRate (wpc), WavpackGetBitsPerSample (wpc), + (WavpackGetMode (wpc) & MODE_FLOAT) ? "float" : "int", WavpackGetNumChannels (wpc), WavpackGetChannelMask (wpc)); + + if (WavpackGetNumSamples (wpc) != (uint32_t) -1) + sprintf (str + strlen (str), "%u;", WavpackGetNumSamples (wpc)); + else + strcat (str, ";"); + + if (WavpackGetMD5Sum (wpc, md5_sum)) { + char md5_string [] = "00000000000000000000000000000000"; + int i; + + for (i = 0; i < 16; ++i) + sprintf (md5_string + (i * 2), "%02x", md5_sum [i]); + + sprintf (str + strlen (str), "%s;", md5_string); + } + else + strcat (str, ";"); + + sprintf (str + strlen (str), "%d;0x%x", WavpackGetVersion (wpc), WavpackGetMode (wpc)); + + if (name && *name != '-') + fprintf (dst, "%s;%s\n", str, name); + else + fprintf (dst, "%s;\n", str); +} + // Dump the specified tag field to the specified stream. Both text and binary tags may be written, // and in Windows the appropriate file mode will be set. If the tag is not found then 0 is returned, // otherwise the length of the data is returned, and this is true even when the file pointer is NULL @@ -1877,9 +2054,9 @@ void display_progress (double file_progress) { char title [40]; - file_progress = (file_index + file_progress) / num_files; - sprintf (title, "%d%% (WvUnpack)", (int) ((file_progress * 100.0) + 0.5)); -#if defined(WIN32) - SetConsoleTitle (title); -#endif + if (!no_console_title) { + file_progress = (file_index + file_progress) / num_files; + sprintf (title, "%d%% (WvUnpack)", (int) ((file_progress * 100.0) + 0.5)); + DoSetConsoleTitle (title); + } } diff --git a/Frameworks/WavPack/WavPack.xcodeproj/project.pbxproj b/Frameworks/WavPack/WavPack.xcodeproj/project.pbxproj index 85b668cd8..782c7c2cb 100644 --- a/Frameworks/WavPack/WavPack.xcodeproj/project.pbxproj +++ b/Frameworks/WavPack/WavPack.xcodeproj/project.pbxproj @@ -283,23 +283,23 @@ GCC_OPTIMIZATION_LEVEL = 0; GCC_PRECOMPILE_PREFIX_HEADER = NO; GCC_PREFIX_HEADER = ""; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + PACK, + UNPACK, + USE_FSTREAMS, + TAGS, + SEEKING, + VER3, + "PACKAGE_NAME='\"wavpack\"'", + "PACKAGE_TARNAME='\"wavpack\"'", + "PACKAGE_VERSION='\"4.70.0\"'", + "PACKAGE_STRING='\"wavpack 4.70.0\"'", + "PACKAGE_BUGREPORT='\"bryant@wavpack.com\"'", + "VERSION_OS='\"Darwin\"'", + ); INFOPLIST_FILE = Info.plist; INSTALL_PATH = "@loader_path/../Frameworks"; - OTHER_CFLAGS = ( - "-DPACK", - "-DUNPACK", - "-DUSE_FSTREAMS", - "-DTAGS", - "-DSEEKING", - "-DVER3", - "-DPACKAGE_NAME=wavpack", - "-DPACKAGE_TARNAME=wavpack", - "-DPACKAGE_VERSION=4.2", - "$(OTHER_CFLAGS_QUOTED_1)", - "-DPACKAGE_BUGREPORT=bryant@wavpack.com", - "-DVERSION_OS=Darwin", - ); - OTHER_CFLAGS_QUOTED_1 = "-DPACKAGE_STRING=\\\"wavpack\\ 4.2\\\""; PRODUCT_NAME = WavPack; SKIP_INSTALL = YES; WRAPPER_EXTENSION = framework; @@ -317,23 +317,22 @@ GCC_MODEL_TUNING = G5; GCC_PRECOMPILE_PREFIX_HEADER = NO; GCC_PREFIX_HEADER = ""; + GCC_PREPROCESSOR_DEFINITIONS = ( + PACK, + UNPACK, + USE_FSTREAMS, + TAGS, + SEEKING, + VER3, + "PACKAGE_NAME='\"wavpack\"'", + "PACKAGE_TARNAME='\"wavpack\"'", + "PACKAGE_VERSION='\"4.70.0\"'", + "PACKAGE_STRING='\"wavpack 4.70.0\"'", + "PACKAGE_BUGREPORT='\"bryant@wavpack.com\"'", + "VERSION_OS='\"Darwin\"'", + ); INFOPLIST_FILE = Info.plist; INSTALL_PATH = "@loader_path/../Frameworks"; - OTHER_CFLAGS = ( - "-DPACK", - "-DUNPACK", - "-DUSE_FSTREAMS", - "-DTAGS", - "-DSEEKING", - "-DVER3", - "-DPACKAGE_NAME=wavpack", - "-DPACKAGE_TARNAME=wavpack", - "-DPACKAGE_VERSION=4.2", - "$(OTHER_CFLAGS_QUOTED_1)", - "-DPACKAGE_BUGREPORT=bryant@wavpack.com", - "-DVERSION_OS=Darwin", - ); - OTHER_CFLAGS_QUOTED_1 = "-DPACKAGE_STRING=\\\"wavpack\\ 4.2\\\""; PRODUCT_NAME = WavPack; SKIP_INSTALL = YES; WRAPPER_EXTENSION = framework;