From 0b14f9a4460a056f2d72a323e10b1e6e32437d76 Mon Sep 17 00:00:00 2001 From: bnnm Date: Tue, 10 Aug 2021 23:51:48 +0200 Subject: [PATCH 01/11] builds: modify how version.h is used to fix issues - version.h is now static (should increase on new releases) - if compiler flag is passed, will try to use version_auto.h (autogen) (auto only on compiler flag to avoid include'ing a non-existant file) - avoid clobbered version.h as may force recompiles --- .gitignore | 2 +- CMakeLists.txt | 4 ++-- Makefile.autotools.am | 2 +- cli/vgmstream_cli.vcxproj | 4 ++-- fb2k/foo_input_vgmstream.vcxproj | 4 ++-- src/libvgmstream.vcxproj | 4 ++-- version-get.sh | 2 +- version-make.bat | 40 ++++++++++++++++++++------------ version-make.sh | 6 ++--- version.h | 18 ++++++++++++-- winamp/in_vgmstream.vcxproj | 4 ++-- xmplay/xmp-vgmstream.vcxproj | 4 ++-- 12 files changed, 59 insertions(+), 35 deletions(-) diff --git a/.gitignore b/.gitignore index dde46b3b..568b68e2 100644 --- a/.gitignore +++ b/.gitignore @@ -44,7 +44,7 @@ Release /xmplay/Release /xmplay/*.dll /dependencies -/version.h +/version_auto.h /msvc-build.config.ps1 /**/vgmstream-win.zip diff --git a/CMakeLists.txt b/CMakeLists.txt index 698fda5f..47262bdc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -88,10 +88,10 @@ if(MSVC) else() set(VGM_VERSION_GENERATOR version-make.sh) endif() -add_custom_command(OUTPUT ${VGM_SOURCE_DIR}/version.h +add_custom_command(OUTPUT ${VGM_SOURCE_DIR}/version_auto.h COMMAND "${VGM_SOURCE_DIR}/${VGM_VERSION_GENERATOR}" DEPENDS ${VGM_SOURCE_DIR}/${VGM_VERSION_GENERATOR}) -add_custom_target(version_h ALL DEPENDS ${VGM_SOURCE_DIR}/version.h) +add_custom_target(version_h ALL DEPENDS ${VGM_SOURCE_DIR}/version_auto.h) # FFmpeg detection if(USE_FFMPEG) diff --git a/Makefile.autotools.am b/Makefile.autotools.am index 41a72740..d34f600f 100644 --- a/Makefile.autotools.am +++ b/Makefile.autotools.am @@ -9,4 +9,4 @@ if HAVE_AUDACIOUS SUBDIRS += audacious endif -EXTRA_DIST = version.h +EXTRA_DIST = version_auto.h diff --git a/cli/vgmstream_cli.vcxproj b/cli/vgmstream_cli.vcxproj index cc5c6a4f..d1045157 100644 --- a/cli/vgmstream_cli.vcxproj +++ b/cli/vgmstream_cli.vcxproj @@ -72,7 +72,7 @@ Disabled ..;../ext_libs/Getopt;../ext_includes;../ext_includes/ffmpeg;$(DependenciesDir)/qaac/mp4v2/include;$(DependenciesDir)/fdk-aac/libSYS/include;$(DependenciesDir)/fdk-aac/libAACdec/include;%(AdditionalIncludeDirectories) - WIN32;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;HAVE_JSON;_DEBUG;_WINDOWS;_CONSOLE;%(PreprocessorDefinitions) + WIN32;VGMSTREAM_VERSION_AUTO;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;HAVE_JSON;_DEBUG;_WINDOWS;_CONSOLE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -97,7 +97,7 @@ ..;../ext_libs/Getopt;../ext_includes;../ext_includes/ffmpeg;$(DependenciesDir)/qaac/mp4v2/include;$(DependenciesDir)/fdk-aac/libSYS/include;$(DependenciesDir)/fdk-aac/libAACdec/include;%(AdditionalIncludeDirectories) - WIN32;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;HAVE_JSON;NDEBUG;_WINDOWS;_CONSOLE;%(PreprocessorDefinitions) + WIN32;VGMSTREAM_VERSION_AUTO;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;HAVE_JSON;NDEBUG;_WINDOWS;_CONSOLE;%(PreprocessorDefinitions) MultiThreaded diff --git a/fb2k/foo_input_vgmstream.vcxproj b/fb2k/foo_input_vgmstream.vcxproj index 066c8d69..9d25ff51 100644 --- a/fb2k/foo_input_vgmstream.vcxproj +++ b/fb2k/foo_input_vgmstream.vcxproj @@ -71,7 +71,7 @@ Disabled ..;../ext_includes;../ext_includes/ffmpeg;$(DependenciesDir)/WTL/Include;$(DependenciesDir)/foobar/foobar2000/SDK;$(DependenciesDir)/foobar/foobar2000/shared;$(DependenciesDir)/foobar/foobar2000;$(DependenciesDir)/qaac/mp4v2/include;$(DependenciesDir)/fdk-aac/libSYS/include;$(DependenciesDir)/fdk-aac/libAACdec/include;%(AdditionalIncludeDirectories) - WIN32;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;_DEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;%(PreprocessorDefinitions) + WIN32;VGMSTREAM_VERSION_AUTO;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;_DEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -97,7 +97,7 @@ ..;../ext_includes;../ext_includes/ffmpeg;$(DependenciesDir)/WTL/Include;$(DependenciesDir)/foobar/foobar2000/SDK;$(DependenciesDir)/foobar/foobar2000/shared;$(DependenciesDir)/foobar/foobar2000;$(DependenciesDir)/qaac/mp4v2/include;$(DependenciesDir)/fdk-aac/libSYS/include;$(DependenciesDir)/fdk-aac/libAACdec/include;%(AdditionalIncludeDirectories) - WIN32;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;NDEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;%(PreprocessorDefinitions) + WIN32;VGMSTREAM_VERSION_AUTO;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;NDEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;%(PreprocessorDefinitions) MultiThreaded diff --git a/src/libvgmstream.vcxproj b/src/libvgmstream.vcxproj index 17546f2c..e13dd4ac 100644 --- a/src/libvgmstream.vcxproj +++ b/src/libvgmstream.vcxproj @@ -59,7 +59,7 @@ Disabled ../ext_includes;../ext_includes/ffmpeg;$(DependenciesDir)/qaac/mp4v2/include;$(DependenciesDir)/fdk-aac/libSYS/include;$(DependenciesDir)/fdk-aac/libAACdec/include;%(AdditionalIncludeDirectories) - WIN32;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_G719;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;USE_ALLOCA;_DEBUG;_LIB;%(PreprocessorDefinitions) + WIN32;VGMSTREAM_VERSION_AUTO;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_G719;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;USE_ALLOCA;_DEBUG;_LIB;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -72,7 +72,7 @@ ../ext_includes;../ext_includes/ffmpeg;$(DependenciesDir)/qaac/mp4v2/include;$(DependenciesDir)/fdk-aac/libSYS/include;$(DependenciesDir)/fdk-aac/libAACdec/include;%(AdditionalIncludeDirectories) - _WIN32_WINNT=0x501;WIN32;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_G719;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;USE_ALLOCA;NDEBUG;_LIB;%(PreprocessorDefinitions) + _WIN32_WINNT=0x501;WIN32;VGMSTREAM_VERSION_AUTO;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_G719;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;USE_ALLOCA;NDEBUG;_LIB;%(PreprocessorDefinitions) MultiThreaded diff --git a/version-get.sh b/version-get.sh index b22b07a4..7fbea41a 100644 --- a/version-get.sh +++ b/version-get.sh @@ -1,6 +1,6 @@ #!/bin/sh -# echo current git version (doesn't make version.h) +# echo current git version (doesn't make version_auto.h) # test if git exists if ! command -v git > /dev/null diff --git a/version-make.bat b/version-make.bat index 8e98334f..b891b69e 100644 --- a/version-make.bat +++ b/version-make.bat @@ -1,37 +1,47 @@ @echo off setlocal enableextensions enabledelayedexpansion -REM creates or updates version.h -REM params: $1=filename (usually version.h), $2=VARNAME (usually VGMSTREAM_VERSION) +REM creates or updates version_auto.h +REM params: $1=filename (usually version_auto.h), $2=VARNAME (usually VGMSTREAM_VERSION) REM defaults set VERSION_DEFAULT=unknown set VERSION_FILE=%1 set VERSION_NAME=%2 -if "%~1" == "" set VERSION_FILE=version.h +if "%~1" == "" set VERSION_FILE=version_auto.h if "%~2" == "" set VERSION_NAME=VGMSTREAM_VERSION -if not "%version%"=="" set version=!version:^:=_! +if not "%VERSION%"=="" set VERSION=!VERSION:^:=_! cd /d "%~dp0" -REM try get version from Git, leave original version.h untouched if not possible -for /f %%v in ('git describe --always') do set version=%%v - -if not "%version%"=="" set version=!version:^:=_! -if not "%version%"=="" goto :got_version - -echo Git version not found, can't autogenerate version.h +REM try get version from Git (dynamic) +:get_version_git +for /f %%v in ('git describe --always') do set VERSION=%%v +if not "%VERSION%"=="" set VERSION=!VERSION:^:=_! +if "%VERSION%"=="" goto :get_version_h +if %VERSION%==%VERSION_DEFAULT% goto :get_version_h +set LINE=#define %VERSION_NAME% "%VERSION%" /* autogenerated */ +echo %LINE% > %VERSION_FILE% goto :exit -REM overwrite version.h -:got_version -if %version%==%VERSION_DEFAULT% goto :exit +REM try to get version from version.h (static) +:get_version_h +echo Git version not found, can't autogenerate version_auto.h +set LINE=#define %VERSION_NAME% "%VERSION_DEFAULT%" /* autogenerated */ +if exist "version.h" ( + for /F "tokens=*" %%v in (version.h) do ( + set TOKEN=%%v + REM set COMP=#define %VERSION_NAME% #todo + if /i "!TOKEN:~0,25!"=="#define VGMSTREAM_VERSION" set LINE=%%v + ) +) -echo #define %VERSION_NAME% "%version%" /* autogenerated */ > %VERSION_FILE% +echo %LINE% > %VERSION_FILE% +goto :exit REM done diff --git a/version-make.sh b/version-make.sh index 107a838f..4ed96d02 100644 --- a/version-make.sh +++ b/version-make.sh @@ -1,8 +1,8 @@ #!/bin/sh -# make current git version (overwrites version.h) +# make current git version (overwrites version_auto.h) VERSION_NAME=VGMSTREAM_VERSION -VERSION_FILE=version.h +VERSION_FILE=version_auto.h # test if git exists @@ -17,5 +17,5 @@ fi if [[ $VERSION != fatal* ]] && [ ! -z "$VERSION" ] ; then echo "#define $VERSION_NAME \"$VERSION\" /* autogenerated */" > $VERSION_FILE else - echo "Git version not found, can't autogenerate version.h" + echo "Git version not found, can't autogenerate version_auto.h" fi; diff --git a/version.h b/version.h index 2301a4bf..332aef33 100644 --- a/version.h +++ b/version.h @@ -1,4 +1,18 @@ +#ifndef _VGMSTREAM_H_ +#define _VGMSTREAM_H_ +/* autogenerated version passed by param */ +//todo detect if VGMSTREAM_VERSION is "" (may happen on script error) +#ifndef VGMSTREAM_VERSION +/* autogenerated version on file */ +#ifdef VGMSTREAM_VERSION_AUTO +#include "version_auto.h" +#else /* Static/fallback version. * Version is autogenerated from Git (passed via compiler args, or updated with scripts), but this file is - * for Git-less builds (not installed or downloaded master) and builds that don't do the above should still work. */ -#define VGMSTREAM_VERSION "unknown" + * for Git-less builds (not installed or downloaded master) and builds that don't do the above should still work + * (compiling a well-behaved src shouldn't depend on calling arbitrary scripts). */ +#define VGMSTREAM_VERSION "r1050" +#endif +#endif + +#endif diff --git a/winamp/in_vgmstream.vcxproj b/winamp/in_vgmstream.vcxproj index f2446e6d..1fece220 100644 --- a/winamp/in_vgmstream.vcxproj +++ b/winamp/in_vgmstream.vcxproj @@ -71,7 +71,7 @@ Disabled ..;../ext_includes;../ext_includes/ffmpeg;$(DependenciesDir)/qaac/mp4v2/include;$(DependenciesDir)/fdk-aac/libSYS/include;$(DependenciesDir)/fdk-aac/libAACdec/include;%(AdditionalIncludeDirectories) - WIN32;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;_DEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;VGM_WINAMP_UNICODE;%(PreprocessorDefinitions) + WIN32;VGMSTREAM_VERSION_AUTO;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;_DEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;VGM_WINAMP_UNICODE;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug @@ -98,7 +98,7 @@ ..;../ext_includes;../ext_includes/ffmpeg;$(DependenciesDir)/qaac/mp4v2/include;$(DependenciesDir)/fdk-aac/libSYS/include;$(DependenciesDir)/fdk-aac/libAACdec/include;%(AdditionalIncludeDirectories) - WIN32;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;NDEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;VGM_WINAMP_UNICODE;%(PreprocessorDefinitions) + WIN32;VGMSTREAM_VERSION_AUTO;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;NDEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;VGM_WINAMP_UNICODE;%(PreprocessorDefinitions) MultiThreaded diff --git a/xmplay/xmp-vgmstream.vcxproj b/xmplay/xmp-vgmstream.vcxproj index a4d144ce..edaa2890 100644 --- a/xmplay/xmp-vgmstream.vcxproj +++ b/xmplay/xmp-vgmstream.vcxproj @@ -62,7 +62,7 @@ Disabled ..;../ext_includes;../ext_includes/ffmpeg;$(DependenciesDir)/qaac/mp4v2/include;$(DependenciesDir)/fdk-aac/libSYS/include;$(DependenciesDir)/fdk-aac/libAACdec/include;%(AdditionalIncludeDirectories) - WIN32;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;_DEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;%(PreprocessorDefinitions) + WIN32;VGMSTREAM_VERSION_AUTO;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;_DEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;%(PreprocessorDefinitions) EnableFastChecks MultiThreadedDebug Level3 @@ -86,7 +86,7 @@ ..;../ext_includes;../ext_includes/ffmpeg;$(DependenciesDir)/qaac/mp4v2/include;$(DependenciesDir)/fdk-aac/libSYS/include;$(DependenciesDir)/fdk-aac/libAACdec/include;%(AdditionalIncludeDirectories) - _WIN32_WINNT=0x501;WIN32;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;NDEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;%(PreprocessorDefinitions) + _WIN32_WINNT=0x501;WIN32;VGMSTREAM_VERSION_AUTO;VGM_USE_VORBIS;VGM_USE_MPEG;VGM_USE_FFMPEG;VGM_USE_G7221;VGM_USE_ATRAC9;VGM_USE_CELT;VGM_USE_SPEEX;NDEBUG;_WINDOWS;_USRDLL;IN_VGMSTREAM_EXPORTS;%(PreprocessorDefinitions) MultiThreaded Level3 ProgramDatabase From 2b042d6eed8099bcce93209c8a306724658a142e Mon Sep 17 00:00:00 2001 From: bnnm Date: Tue, 10 Aug 2021 23:52:53 +0200 Subject: [PATCH 02/11] autotools: enable ffmpeg as should now build ok --- configure.ac | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configure.ac b/configure.ac index b43e5489..e7d84e85 100644 --- a/configure.ac +++ b/configure.ac @@ -42,9 +42,9 @@ PKG_CHECK_MODULES(SPEEX, [speex], have_libspeex=yes, AM_CONDITIONAL(HAVE_LIBSPEEX, test "$have_libspeex" = yes) have_ffmpeg=no -#PKG_CHECK_MODULES(FFMPEG, [libavformat libavcodec libavutil libswresample], have_ffmpeg=yes, -# [AC_MSG_WARN([Cannot find ffmpeg - will not enable FFmpeg formats])] -#) +PKG_CHECK_MODULES(FFMPEG, [libavformat libavcodec libavutil libswresample], have_ffmpeg=yes, + [AC_MSG_WARN([Cannot find ffmpeg - will not enable FFmpeg formats])] +) AM_CONDITIONAL(HAVE_FFMPEG, test "$have_ffmpeg" = yes) have_audacious=no From e70cc00face2dc3a584a2480a402cf9cb87efd5a Mon Sep 17 00:00:00 2001 From: bnnm Date: Tue, 10 Aug 2021 23:54:04 +0200 Subject: [PATCH 03/11] makefiles: fixes to build with external libs --- Makefile | 182 ++++++++++++++++++++++++++++++---------------- cli/Makefile | 32 +++++--- ext_libs/Makefile | 8 +- 3 files changed, 145 insertions(+), 77 deletions(-) diff --git a/Makefile b/Makefile index 62ddb6a7..eba01c62 100644 --- a/Makefile +++ b/Makefile @@ -89,81 +89,141 @@ LIBS_LDFLAGS= LIBS_TARGET_EXT_LIBS= # config libs -VGM_ENABLE_G7221 = 1 -ifeq ($(VGM_ENABLE_G7221),1) +VGM_G7221 = 1 +ifneq ($(VGM_G7221),0) LIBS_CFLAGS += -DVGM_USE_G7221 endif ### external libs +# (call "make VGM_xxx = 0/1" to override 0/1 defaults, as Make does) ifeq ($(TARGET_OS),Windows_NT) + # enabled by default on Windows + VGM_VORBIS = 1 + ifneq ($(VGM_VORBIS),0) + LIBS_CFLAGS += -DVGM_USE_VORBIS + LIBS_LDFLAGS += -lvorbis + LIBS_TARGET_EXT_LIBS += libvorbis.a + endif -VGM_ENABLE_VORBIS = 1 -ifeq ($(VGM_ENABLE_VORBIS),1) - LIBS_CFLAGS += -DVGM_USE_VORBIS - LIBS_LDFLAGS += -lvorbis - LIBS_TARGET_EXT_LIBS += libvorbis.a + VGM_MPEG = 1 + ifneq ($(VGM_MPEG),0) + LIBS_CFLAGS += -DVGM_USE_MPEG + LIBS_LDFLAGS += -lmpg123-0 + LIBS_TARGET_EXT_LIBS += libmpg123-0.a + endif + + VGM_G719 = 1 + ifneq ($(VGM_G719),0) + LIBS_CFLAGS += -DVGM_USE_G719 + LIBS_LDFLAGS += -lg719_decode + LIBS_TARGET_EXT_LIBS += libg719_decode.a + endif + + VGM_MAT3P = 0 + ifneq ($(VGM_MAT3P),0) + LIBS_CFLAGS += -DVGM_USE_MAIATRAC3PLUS + LIBS_LDFLAGS += -lat3plusdecoder + LIBS_TARGET_EXT_LIBS += libat3plusdecoder.a + endif + + VGM_FFMPEG = 1 + ifneq ($(VGM_FFMPEG),0) + LIBS_CFLAGS += -DVGM_USE_FFMPEG + LIBS_LDFLAGS += -lavcodec -lavformat -lavutil -lswresample + LIBS_TARGET_EXT_LIBS += libavcodec.a libavformat.a libavutil.a libswresample.a + endif + + VGM_ATRAC9 = 1 + ifneq ($(VGM_ATRAC9),0) + LIBS_CFLAGS += -DVGM_USE_ATRAC9 + LIBS_LDFLAGS += -latrac9 + LIBS_TARGET_EXT_LIBS += libatrac9.a + endif + + VGM_CELT = 1 + ifneq ($(VGM_CELT),0) + LIBS_CFLAGS += -DVGM_USE_CELT + LIBS_LDFLAGS += -lcelt-0061 -lcelt-0110 + LIBS_TARGET_EXT_LIBS += libcelt-0061.a libcelt-0110.a + endif + + VGM_SPEEX = 1 + ifneq ($(VGM_SPEEX),0) + LIBS_CFLAGS += -DVGM_USE_SPEEX + LIBS_LDFLAGS += -L../ext_libs/libspeex -lspeex + LIBS_TARGET_EXT_LIBS += libspeex/libspeex.a + endif + +else + + # must install system libs and enable manually on Linux + VGM_VORBIS = 0 + ifneq ($(VGM_VORBIS),0) + LIBS_CFLAGS += -DVGM_USE_VORBIS + LIBS_LDFLAGS += -lvorbis -lvorbisfile + endif + + VGM_MPEG = 0 + ifneq ($(VGM_MPEG),0) + LIBS_CFLAGS += -DVGM_USE_MPEG + LIBS_LDFLAGS += -lmpg123 + endif + + VGM_G719 = 0 + ifneq ($(VGM_G719),0) + LIBS_CFLAGS += -DVGM_USE_G719 + LIBS_LDFLAGS += -lg719_decode + endif + + VGM_MAT3P = 0 + ifneq ($(VGM_MAT3P),0) + LIBS_CFLAGS += -DVGM_USE_MAIATRAC3PLUS + LIBS_LDFLAGS += -lat3plusdecoder + endif + + VGM_FFMPEG = 0 + ifneq ($(VGM_FFMPEG),0) + LIBS_CFLAGS += -DVGM_USE_FFMPEG + LIBS_LDFLAGS += -lavcodec -lavformat -lavutil -lswresample + endif + + VGM_ATRAC9 = 0 + ifneq ($(VGM_ATRAC9),0) + LIBS_CFLAGS += -DVGM_USE_ATRAC9 + ifeq ($(VGM_ATRAC9),1) + LIBS_LDFLAGS += -latrac9 + endif + ifeq ($(VGM_ATRAC9),2) + LIBS_LDFLAGS += -l:libatrac9.a + endif + endif + + VGM_CELT = 0 + ifneq ($(VGM_CELT),0) + LIBS_CFLAGS += -DVGM_USE_CELT + ifeq ($(VGM_CELT),1) + LIBS_LDFLAGS += -lcelt-0061 -lcelt-0110 + endif + ifeq ($(VGM_CELT),2) + LIBS_LDFLAGS += -l:libcelt-0061.a -l:libcelt-0110.a + endif + endif + + VGM_SPEEX = 0 + ifneq ($(VGM_SPEEX),0) + LIBS_CFLAGS += -DVGM_USE_SPEEX + LIBS_LDFLAGS += -lspeex + endif endif -VGM_ENABLE_MPEG = 1 -ifeq ($(VGM_ENABLE_MPEG),1) - LIBS_CFLAGS += -DVGM_USE_MPEG - LIBS_LDFLAGS += -lmpg123-0 - LIBS_TARGET_EXT_LIBS += libmpg123-0.a -endif - -VGM_ENABLE_G719 = 1 -ifeq ($(VGM_ENABLE_G719),1) - LIBS_CFLAGS += -DVGM_USE_G719 - LIBS_LDFLAGS += -lg719_decode - LIBS_TARGET_EXT_LIBS += libg719_decode.a -endif - -VGM_ENABLE_MAIATRAC3PLUS = 0 -ifeq ($(VGM_ENABLE_MAIATRAC3PLUS),1) - LIBS_CFLAGS += -DVGM_USE_MAIATRAC3PLUS - LIBS_LDFLAGS += -lat3plusdecoder - LIBS_TARGET_EXT_LIBS += libat3plusdecoder.a -endif - -VGM_ENABLE_FFMPEG = 1 -ifeq ($(VGM_ENABLE_FFMPEG),1) - LIBS_CFLAGS += -DVGM_USE_FFMPEG - LIBS_LDFLAGS += -lavcodec -lavformat -lavutil -lswresample - LIBS_TARGET_EXT_LIBS += libavcodec.a libavformat.a libavutil.a libswresample.a -endif - -VGM_ENABLE_ATRAC9 = 1 -ifeq ($(VGM_ENABLE_ATRAC9),1) - LIBS_CFLAGS += -DVGM_USE_ATRAC9 - LIBS_LDFLAGS += -latrac9 - LIBS_TARGET_EXT_LIBS += libatrac9.a -endif - -VGM_ENABLE_CELT = 1 -ifeq ($(VGM_ENABLE_CELT),1) - LIBS_CFLAGS += -DVGM_USE_CELT - LIBS_LDFLAGS += -lcelt-0061 -lcelt-0110 - LIBS_TARGET_EXT_LIBS += libcelt-0061.a libcelt-0110.a -endif - -VGM_ENABLE_SPEEX = 1 -ifeq ($(VGM_ENABLE_SPEEX),1) - LIBS_CFLAGS += -DVGM_USE_SPEEX - LIBS_LDFLAGS += -L../ext_libs/libspeex -lspeex - LIBS_TARGET_EXT_LIBS += libspeex/libspeex.a -endif - -endif #if WIN32 - - export DEF_CFLAGS LIBS_CFLAGS LIBS_LDFLAGS LIBS_TARGET_EXT_LIBS ############################################################################### ### internal defs -ZIP_FILES = COPYING -ZIP_FILES+= README.md +ZIP_FILES = COPYING +ZIP_FILES+= README.md ZIP_FILES+= cli/test.exe ZIP_FILES+= winamp/in_vgmstream.dll ZIP_FILES+= xmplay/xmp-vgmstream.dll diff --git a/cli/Makefile b/cli/Makefile index dac9f104..9400399f 100644 --- a/cli/Makefile +++ b/cli/Makefile @@ -5,30 +5,38 @@ ############################################################################### ### main defs +LIBAO_IPATH = ../../libao/include +LIBAO_LPATH = ../../libao/bin + + +CFLAGS += $(DEF_CFLAGS) -DVAR_ARRAYS $(EXTRA_CFLAGS) +LDFLAGS += -L../src -lvgmstream -lm $(EXTRA_LDFLAGS) +TARGET_EXT_LIBS = + ifeq ($(TARGET_OS),Windows_NT) OUTPUT_CLI = test.exe OUTPUT_123 = vgmstream123.exe + + # -DUSE_ALLOCA + CFLAGS += -DWIN32 -I../ext_includes -I../ext_libs/Getopt -I../ext_includes/ffmpeg + LDFLAGS += -L../ext_libs + + LIBAO_INC = -I$(LIBAO_IPATH) + LIBAO_LIB = -L$(LIBAO_LPATH) -lao else OUTPUT_CLI = vgmstream-cli OUTPUT_123 = vgmstream123 -endif -# -DUSE_ALLOCA -ifeq ($(TARGET_OS),Windows_NT) - CFLAGS += -DWIN32 -I../ext_libs/Getopt -I../ext_includes/ffmpeg -endif + #todo move clhca/etc and remove + CFLAGS += -I../ext_includes -CFLAGS += $(DEF_CFLAGS) -DVAR_ARRAYS -I../ext_includes $(EXTRA_CFLAGS) -LDFLAGS += -L../src -L../ext_libs -lvgmstream -lm $(EXTRA_LDFLAGS) -TARGET_EXT_LIBS = + LIBAO_LIB = -lao +endif CFLAGS += $(LIBS_CFLAGS) LDFLAGS += $(LIBS_LDFLAGS) TARGET_EXT_LIBS += $(LIBS_TARGET_EXT_LIBS) -LIBAO_INC_PATH = ../../libao/include -LIBAO_LIB_PATH = ../../libao/bin - export CFLAGS LDFLAGS @@ -41,7 +49,7 @@ vgmstream_cli: libvgmstream.a $(TARGET_EXT_LIBS) $(STRIP) $(OUTPUT_CLI) vgmstream123: libvgmstream.a $(TARGET_EXT_LIBS) - $(CC) $(CFLAGS) -I$(LIBAO_INC_PATH) "-DVGMSTREAM_VERSION=\"$(VGMSTREAM_VERSION_PREV)\"" vgmstream123.c $(LDFLAGS) -L$(LIBAO_LIB_PATH) -lao -o $(OUTPUT_123) + $(CC) $(CFLAGS) $(LIBAO_INC) "-DVGMSTREAM_VERSION=\"$(VGMSTREAM_VERSION_PREV)\"" vgmstream123.c $(LDFLAGS) $(LIBAO_LIB) -o $(OUTPUT_123) $(STRIP) $(OUTPUT_123) libvgmstream.a: diff --git a/ext_libs/Makefile b/ext_libs/Makefile index c96dbe77..73a3096b 100644 --- a/ext_libs/Makefile +++ b/ext_libs/Makefile @@ -2,10 +2,10 @@ # external libs # -# needed? -ifneq ($(TARGET_OS),Windows_NT) -$(error option must be built with TARGET_OS = Windows_NT) -endif +# don't barf in case it's target "clean" +#ifneq ($(TARGET_OS),Windows_NT) +#$(error option must be built with TARGET_OS = Windows_NT) +#endif libvorbis.a: libvorbis.def From fefc40dcf76f0df5b925c891bd2eb346525005a0 Mon Sep 17 00:00:00 2001 From: bnnm Date: Tue, 10 Aug 2021 23:55:03 +0200 Subject: [PATCH 04/11] build: example linux sh with extra libs (beta) --- doc/BUILD.md | 36 +++++++--- make-build.sh | 185 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 213 insertions(+), 8 deletions(-) create mode 100644 make-build.sh diff --git a/doc/BUILD.md b/doc/BUILD.md index 6f98f681..db91ad67 100644 --- a/doc/BUILD.md +++ b/doc/BUILD.md @@ -70,7 +70,21 @@ It's also possible to call MSBuild and pass those values from the CMD, see fooba Once finished resulting binaries are in the *./Release* folder. Remember you need to copy extra `.dll` to run them (see [README.md](../README.md)). -**For GCC/CLang**: there are basic Makefiles that work like usual with *make* (like `make vgmstream_cli EXTRA_CFLAGS="-DVGM_DEBUG_OUTPUT`). On Windows this compiles with extra libs enabled, but not on Linux (try CMake or autotools for those). Artifacts are usually in their subdir (*./cli*, *./winamp*, etc). +**For GCC/CLang**: there are basic Makefiles that work like usual with *make* (like `make vgmstream_cli EXTRA_CFLAGS="-DVGM_DEBUG_OUTPUT`). Artifacts are usually in their subdir (*./cli*, *./winamp*, etc). + +On Windows this compiles with extra libs enabled by default. On Linux there is no fancy autodetection (try CMake or autotools for that), so you need to make sure libs are in your system and pass flags to enable them manually (install/compile libs then `make vgmstream_cli VGM_VORBIS=1 ...`). Check or run `make-build.sh` for a basic example that builds CLI and vgmstream123 with most libs enabled for a Ubuntu-style distro (if you get errors on your system just tweak or comment out offending parts). + +Linux example: +``` +sudo apt-get install -y git + +git clone https://github.com/vgmstream/vgmstream +cd vgmstream +chmod +x version-get.sh version-make.sh make-build.sh + +# warning: installs stuff, check all "apt install" +./make-build.sh +``` ### CMake (builds) Tool used to generate common build files (for *make*, *VS/MSBuild*, etc), that in turn can be used to compile vgmstream's modules instead of existing scripts/files. Needs v3.6 or later: @@ -138,7 +152,7 @@ If you use Mac (or Linux), there is a *Homebrew* script that may automate the pr You may try CMake instead as it may be simpler and handle libs better. Some older distros may not work though (CMake version needs to recognize FILTER command). You may also need to install resulting artifacts manually. Check the *CMAKE.md* doc for some extra info too. ``` sudo apt-get update -sudo apt-get install -y gcc g++ make build-essential +sudo apt-get install -y gcc g++ make build-essential git sudo apt-get install -y libmpg123-dev libvorbis-dev libspeex-dev sudo apt-get install -y libavformat-dev libavcodec-dev libavutil-dev libswresample-dev sudo apt-get install -y libao-dev audacious-dev @@ -161,7 +175,6 @@ set PATH=C:\Program Files (x86)\mingw-w64\i686-5.4.0-win32-sjlj-rt_v5-rev0\mingw cd vgmstream mingw32-make.exe vgmstream_cli -f Makefile ^ - VGM_ENABLE_MAIATRAC3PLUS=0 ^ EXTRA_CFLAGS="-DVGM_DEBUG_OUTPUT -g -Wimplicit-function-declaration" ^ SHELL=sh.exe CC=gcc.exe AR=ar.exe STRIP=strip.exe DLLTOOL=dlltool.exe WINDRES=windres.exe ^ STRIP=echo ^ @@ -246,7 +259,7 @@ Take note of other plugins stealing extensions (see README). To change Audacious You can try building with CMake. Some older distros may not work though (CMake version needs to recognize FILTER command), and may need to install resulting artifacts manually (check ./audacious dir). ``` sudo apt-get update -sudo apt-get install -y gcc g++ make build-essential +sudo apt-get install -y gcc g++ make build-essential git sudo apt-get install -y libmpg123-dev libvorbis-dev libspeex-dev sudo apt-get install -y libavformat-dev libavcodec-dev libavutil-dev libswresample-dev sudo apt-get install -y libao-dev audacious-dev @@ -266,9 +279,8 @@ Instead of CMake you can use autotools. Terminal example, assuming a Ubuntu-base # default requirements sudo apt-get update -sudo apt-get install gcc g++ make +sudo apt-get install gcc g++ make git sudo apt-get install autoconf automake libtool -sudo apt-get install git # vgmstream dependencies sudo apt-get install libmpg123-dev libvorbis-dev libspeex-dev #sudo apt-get install libavformat-dev libavcodec-dev libavutil-dev libswresample-dev @@ -367,6 +379,7 @@ MSVC needs a .lib helper to link .dll files, but libs below usually only create Adds support for Vorbis, inside Ogg as `.ogg` (plain or encrypted) or custom variations like `.wem`, `.fsb`, `.ogl`, etc. - Source: http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.6.zip - DLL: `libvorbis.dll` +- lib: `-lvorbis -lvorbisfile` - licensed under the 3-clause BSD license. Should be buildable with MSVC (in /win32 dir are .sln files) or autotools (use `autogen.sh`). @@ -377,6 +390,7 @@ Adds support for MPEG (MP1/MP2/MP3), used in formats that may have custom MPEG l - Source: https://sourceforge.net/projects/mpg123/files/mpg123/1.25.10/ - Builds: http://www.mpg123.de/download/win32/1.25.10/ - DLL: `libmpg123-0.dll` +- lib: `-lmpg123` - licensed under the LGPL v2.1 Must use autotools (sh configure, make, make install), though some scripts simplify the process: `makedll.sh`, `windows-builds.sh`. @@ -386,6 +400,7 @@ Must use autotools (sh configure, make, make install), though some scripts simpl Adds support for ITU-T G.719 (standardization of Polycom Siren 22), used in a few Namco `.bnsf` games. - Source: https://github.com/kode54/libg719_decode - DLL: `libg719_decode.dll` +- lib: --- - unknown license (possibly invalid and Polycom's) Use MSVC (use `g719.sln`). It can be built with GCC too, but you'll need to manually create scripts/makefiles. @@ -395,6 +410,7 @@ Use MSVC (use `g719.sln`). It can be built with GCC too, but you'll need to manu Adds support for multiple codecs: ATRAC3 (`.at3`), ATRAC3plus (`.at3`), XMA1/2 (`.xma`), WMA v1 (`.wma`), WMA v2 (`.wma`), WMAPro (`.xwma`), AAC (`.mp4`, `.aac`), Bink (`.bik`), AC3/SPDIF (`.ac3`), Opus (`.opus`), Musepack (`.mpc`), FLAC (`.flac`), etc. - Source: https://github.com/FFmpeg/FFmpeg/ - DLLs: `avcodec-vgmstream-58.dll`, `avformat-vgmstream-58.dll`, `avutil-vgmstream-56.dll`, `swresample-vgmstream-3.dll` +- lib: `-lavcodec -lavformat -lavutil -lswresample` - primarily licensed under the LGPL v2.1 or later, with portions licensed under the GPL v2 vgmstream's FFmpeg builds for Windows remove many unnecessary parts of FFmpeg to trim down its gigantic size, and are also built with the "vgmstream-" prefix to avoid clashing with other plugins. Current options can be seen in `ffmpeg_options.txt`. Linux usually links to the system's FFmpeg without issues. @@ -410,6 +426,7 @@ Both may need yasm somewhere in PATH to properly compile: https://yasm.tortall.n Adds support for ATRAC9, used in `.at9` and other formats for the PS4 and Vita. - Source: https://github.com/Thealexbarney/LibAtrac9 - DLL: `libatrac9.dll` +- lib: `-latrac9` / `-l:libatrac9.a` - licensed under the MIT license Use MSCV and `libatrac9.sln`, or GCC and the Makefile included. @@ -420,6 +437,7 @@ Adds support for FSB CELT versions 0.6.1 and 0.11.0, used in a handful of older - Source (0.6.1): http://downloads.us.xiph.org/releases/celt/celt-0.6.1.tar.gz - Source (0.11.0): http://downloads.xiph.org/releases/celt/celt-0.11.0.tar.gz - DLL: `libcelt-0061.dll`, `libcelt-0110.dll` +- lib: `-lcelt-0061` `-lcelt-0110` / `-l:libcelt-0110.a` `-l:libcelt-0061.a` - licensed under the MIT license FSB uses two incompatible, older libcelt versions. Both libraries export the same symbols so normally can't coexist together. To get them working we need to make sure symbols are renamed first. This may be solved in various ways: @@ -433,7 +451,7 @@ To compile we'll use autotools with GCC preprocessor renaming: - in the celt-0.6.1 dir: ``` # creates Makefiles with Automake - sh.exe ./configure --build=mingw32 --prefix=/c/celt-0.11.0/bin/ --exec-prefix=/c/celt-0.11.0/bin/ + sh.exe ./configure --build=mingw32 --prefix=/c/celt0.6.1/bin/ --exec-prefix=/c/celt-0.6.1/bin/ # LDFLAGS are needed to create the .dll (Automake whinning) # CFLAGS rename a few CELT functions (we don't import the rest so they won't clash) @@ -456,17 +474,19 @@ To compile we'll use autotools with GCC preprocessor renaming: For Linux, an option is using AUR's scripts (https://aur.archlinux.org/packages/vgmstream-git/) that similarly patch celt libs in PKGBUILD. +You can also get them from the official git (https://gitlab.xiph.org/xiph/celt) call `./autogen.sh` first, then pass call configure/make with renames (see `./make-build.sh`). ### libspeex Adds support for Speex (inside custom containers), used in a few *EA* formats (`.sns`, `.sps`) for voices. - Source: http://downloads.us.xiph.org/releases/speex/speex-1.2.0.tar.gz - DLL: `libspeex.dll` +- lib: `-lspeex` - licensed under the Xiph.Org variant of the BSD license. https://www.xiph.org/licenses/bsd/speex/ Should be buildable with MSVC (in /win32 dir are .sln files, but not up to date and may need to convert .vcproj to vcxproj) or autotools (use `autogen.sh`, or script below). -You can also find a release on Github (https://github.com/xiph/speex/releases/tag/Speex-1.2.0). It has newer timestamps and some different helper files vs Xiph's release, but actual lib should be the same. Notably, Github's release *needs* `autogen.sh` that calls `autoreconf` to generate a base `configure` script, while Xiph's pre-includes `configure`. Since getting autoreconf working on Windows can be quite involved, Xiph's release is recommended. +You can also find a release on Github (https://github.com/xiph/speex/releases/tag/Speex-1.2.0). It has newer timestamps and some different helper files vs Xiph's release, but actual lib should be the same. Notably, Github's release *needs* `autogen.sh` that calls `autoreconf` to generate a base `configure` script, while Xiph's pre-includes `configure`. Since getting autoreconf working on Windows can be quite involved, Xiph's release is recommended on that platform. Windows CMD example: ``` diff --git a/make-build.sh b/make-build.sh new file mode 100644 index 00000000..c201f464 --- /dev/null +++ b/make-build.sh @@ -0,0 +1,185 @@ +#!/bin/sh + +# example script that builds vgmstream with most libs enabled using the basic makefiles +# (needs some manual fiddling) +# most libs use system libs if possible, but should be possible to download them, compile, and +# pass INCS/LIBSs that use static libs + +# todo more testing +# - don't use ext_libs includes for linux (uses system libs) +# - libcelt 0.6 works but 11.0 gives "Floating point exception (core dumped)" (VM?) +exit + +# config for make +INCS= +LIBS= +FLAGS= + +############################################################################### +# base deps +sudo apt-get install -y gcc g++ make build-essential git + + +############################################################################### +# vgmstream123 deps +sudo apt-get install -y libao-dev + + +############################################################################### +# vorbis deps +sudo apt-get install -y libvorbis-dev +FLAGS+=" VGM_VORBIS=1" + + +############################################################################### +# mpeg deps +sudo apt-get install -y libmpg123-dev +FLAGS+=" VGM_MPEG=1" + + +############################################################################### +# speex deps +sudo apt-get install -y libspeex-dev +FLAGS+=" VGM_SPEEX=1" + + +############################################################################### +# ffmpeg deps +sudo apt-get install -y libavformat-dev libavcodec-dev libavutil-dev libswresample-dev +FLAGS+=" VGM_FFMPEG=1" + + +############################################################################### +# atrac9 deps (compile) +mkdir dependencies +cd dependencies +git clone https://github.com/Thealexbarney/LibAtrac9 +cd LibAtrac9/C +make +cd ../../../ + +FLAGS+=" VGM_ATRAC9=2" +#INCS+=" -I../dependencies/LibAtrac9/C/src" +LIBS+=" -L../dependencies/LibAtrac9/C/bin" + + +############################################################################### +# celt deps (compile x2) +mkdir dependencies +cd dependencies + +# used renames followed by unused renamed (but seems needed to avoid clashes) +CELT0061_RENAMES=" \ + -Dcelt_decode=celt_0061_decode \ + -Dcelt_decoder_create=celt_0061_decoder_create \ + -Dcelt_decoder_destroy=celt_0061_decoder_destroy \ + -Dcelt_mode_create=celt_0061_mode_create \ + -Dcelt_mode_destroy=celt_0061_mode_destroy \ + -Dcelt_mode_info=celt_0061_mode_info \ + \ + -Dalg_quant=alg_quant_0061 \ + -Dalg_unquant=alg_unquant_0061 \ + -Dcelt_decoder_create_custom=celt_decoder_create_custom_0061 \ + -Dcelt_encoder_destroy=celt_encoder_destroy_0061 \ + -Dcelt_encoder_create=celt_encoder_create_0061 \ + -Dcelt_encode=celt_encode_0061 \ + -Dcelt_encode_float=celt_encode_float_0061 \ + -Dcelt_encoder_ctl=celt_encoder_ctl_0061 \ + -Dcelt_decode_float=celt_decode_float_0061 \ + -Dcelt_decoder_ctl=celt_decoder_ctl_0061 \ + -Dcompute_allocation=compute_allocation_0061 \ + -Dcompute_band_energies=compute_band_energies_0061 \ + -Ddenormalise_bands=denormalise_bands_0061 \ + -Dec_dec_init=ec_dec_init_0061 \ + -Dec_decode=ec_decode_0061 \ + -Dec_decode_bin=ec_decode_bin_0061 \ + -Dec_dec_update=ec_dec_update_0061 \ + -Dec_dec_uint=ec_dec_uint_0061 \ + -Dec_dec_bits=ec_dec_bits_0061 \ + -Dec_enc_init=ec_enc_init_0061 \ + -Dec_encode=ec_encode_0061 \ + -Dec_encode_bin=ec_encode_bin_0061 \ + -Dec_enc_uint=ec_enc_uint_0061 \ + -Dec_enc_bits=ec_enc_bits_0061 \ + -Dec_enc_done=ec_enc_done_0061 \ + -Dnormalise_bands=normalise_bands_0061 \ + -Drenormalise_vector=renormalise_vector_0061 \ + -Dquant_coarse_energy=quant_coarse_energy_0061 \ + -Dquant_fine_energy=quant_fine_energy_0061 \ + -Dquant_energy_finalise=quant_energy_finalise_0061 \ + -Dunquant_coarse_energy=unquant_coarse_energy_0061 \ + -Dunquant_energy_finalise=unquant_energy_finalise_0061 \ + -Dunquant_fine_energy=unquant_fine_energy_0061 \ + " +# same as the above but I don't know sh enough to normalize +CELT0110_RENAMES=" \ + -Dcelt_decode=celt_0110_decode \ + -Dcelt_decoder_create_custom=celt_0110_decoder_create_custom \ + -Dcelt_decoder_destroy=celt_0110_decoder_destroy \ + -Dcelt_mode_create=celt_0110_mode_create \ + -Dcelt_mode_destroy=celt_0110_mode_destroy \ + -Dcelt_mode_info=celt_0110_mode_info \ + \ + -Dalg_quant=alg_quant_0110 \ + -Dalg_unquant=alg_unquant_0110 \ + -Dcelt_encoder_destroy=celt_encoder_destroy_0110 \ + -Dcelt_encoder_create=celt_encoder_create_0110 \ + -Dcelt_encode=celt_encode_0110 \ + -Dcelt_encode_float=celt_encode_float_0110 \ + -Dcelt_encoder_ctl=celt_encoder_ctl_0110 \ + -Dcelt_decode_float=celt_decode_float_0110 \ + -Dcelt_decoder_ctl=celt_decoder_ctl_0110 \ + -Dcompute_allocation=compute_allocation_0110 \ + -Dcompute_band_energies=compute_band_energies_0110 \ + -Ddenormalise_bands=denormalise_bands_0110 \ + -Dec_dec_init=ec_dec_init_0110 \ + -Dec_decode=ec_decode_0110 \ + -Dec_decode_bin=ec_decode_bin_0110 \ + -Dec_dec_update=ec_dec_update_0110 \ + -Dec_dec_uint=ec_dec_uint_0110 \ + -Dec_dec_bits=ec_dec_bits_0110 \ + -Dec_enc_init=ec_enc_init_0110 \ + -Dec_encode=ec_encode_0110 \ + -Dec_encode_bin=ec_encode_bin_0110 \ + -Dec_enc_uint=ec_enc_uint_0110 \ + -Dec_enc_bits=ec_enc_bits_0110 \ + -Dec_enc_done=ec_enc_done_0110 \ + -Dnormalise_bands=normalise_bands_0110 \ + -Drenormalise_vector=renormalise_vector_0110 \ + -Dquant_coarse_energy=quant_coarse_energy_0110 \ + -Dquant_fine_energy=quant_fine_energy_0110 \ + -Dquant_energy_finalise=quant_energy_finalise_0110 \ + -Dunquant_coarse_energy=unquant_coarse_energy_0110 \ + -Dunquant_energy_finalise=unquant_energy_finalise_0110 \ + -Dunquant_fine_energy=unquant_fine_energy_0110 \ + " + + +git clone --depth 1 --branch v0.6.1 https://gitlab.xiph.org/xiph/celt.git celt-0061 +cd celt-0061 +./autogen.sh +./configure +make LDFLAGS="-no-undefined" AM_CFLAGS="$CELT0061_RENAMES" +mv ./libcelt/.libs/libcelt.a ./libcelt/.libs/libcelt-0061.a +cd .. + +git clone --depth 1 --branch v0.11 https://gitlab.xiph.org/xiph/celt.git celt-0110 +cd celt-0110 +./autogen.sh +./configure +make LDFLAGS="-no-undefined" AM_CFLAGS="-DCUSTOM_MODES=1 $CELT0110_RENAMES" +mv ./libcelt/.libs/libcelt0.a ./libcelt/.libs/libcelt-0110.a + +cd .. + +cd .. + +FLAGS+="VGM_CELT=2" +#INCS+=" -I../dependencies/celt-0061/libcelt/.libs/" +LIBS+=" -L../dependencies/celt-0061/libcelt/.libs/ -L../dependencies/celt-0110/libcelt/.libs/" + + +############################################################################### +# vgmstream +make vgmstream_cli $FLAGS EXTRA_CFLAGS=$INCS EXTRA_LDFLAGS=$LIBS +make vgmstream123 $FLAGS EXTRA_CFLAGS=$INCS EXTRA_LDFLAGS=$LIBS From ad21706fcbec8b22def257eff09dfe3ef8ce231f Mon Sep 17 00:00:00 2001 From: bnnm Date: Wed, 11 Aug 2021 23:57:36 +0200 Subject: [PATCH 05/11] build: fix rebuild then version doesn't change --- version-make.bat | 25 ++++++++++++++++++++----- version-make.sh | 28 ++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 9 deletions(-) diff --git a/version-make.bat b/version-make.bat index b891b69e..b9a6667c 100644 --- a/version-make.bat +++ b/version-make.bat @@ -13,7 +13,6 @@ if "%~1" == "" set VERSION_FILE=version_auto.h if "%~2" == "" set VERSION_NAME=VGMSTREAM_VERSION if not "%VERSION%"=="" set VERSION=!VERSION:^:=_! - cd /d "%~dp0" @@ -24,13 +23,12 @@ if not "%VERSION%"=="" set VERSION=!VERSION:^:=_! if "%VERSION%"=="" goto :get_version_h if %VERSION%==%VERSION_DEFAULT% goto :get_version_h set LINE=#define %VERSION_NAME% "%VERSION%" /* autogenerated */ -echo %LINE% > %VERSION_FILE% -goto :exit +goto :got_version REM try to get version from version.h (static) :get_version_h -echo Git version not found, can't autogenerate version_auto.h +echo Git version not found, can't autogenerate version (using default) set LINE=#define %VERSION_NAME% "%VERSION_DEFAULT%" /* autogenerated */ if exist "version.h" ( for /F "tokens=*" %%v in (version.h) do ( @@ -39,10 +37,27 @@ if exist "version.h" ( if /i "!TOKEN:~0,25!"=="#define VGMSTREAM_VERSION" set LINE=%%v ) ) +goto :got_version -echo %LINE% > %VERSION_FILE% + +REM avoid overwritting if contents are the same, as some systems rebuild on timestamp +:got_version +set LINE_ORIGINAL=none +if exist %VERSION_FILE% set /p LINE_ORIGINAL=<%VERSION_FILE% +if not "%LINE%"=="%LINE_ORIGINAL%" ( + REM no spaces! + echo %LINE%>%VERSION_FILE% +) goto :exit +REM * alt full file comp test +REM echo %LINE% > %VERSION_FILE%_temp +REM echo n | comp %VERSION_FILE%_temp %VERSION_FILE% > NUL 2> NUL +REM if not errorlevel 1 goto :got_version_done +REM copy /y %VERSION_FILE%_temp %VERSION_FILE% > NUL 2> NUL +REM :got_version_done +REM del %VERSION_FILE%_temp +REM :exit REM done :exit diff --git a/version-make.sh b/version-make.sh index 4ed96d02..bbc2adb8 100644 --- a/version-make.sh +++ b/version-make.sh @@ -1,11 +1,12 @@ #!/bin/sh # make current git version (overwrites version_auto.h) +VERSION_DEFAULT=unknown VERSION_NAME=VGMSTREAM_VERSION VERSION_FILE=version_auto.h -# test if git exists +# try get version from Git (dynamic) if ! command -v git > /dev/null ; then VERSION="" else @@ -15,7 +16,26 @@ fi # ignore git stderr "fatal:*" or blank if [[ $VERSION != fatal* ]] && [ ! -z "$VERSION" ] ; then - echo "#define $VERSION_NAME \"$VERSION\" /* autogenerated */" > $VERSION_FILE + LINE="#define $VERSION_NAME \"$VERSION\" /* autogenerated */" else - echo "Git version not found, can't autogenerate version_auto.h" -fi; + # try to get version from version.h (static) + echo "Git version not found, can't autogenerate version (using default)" + LINE="#define $VERSION_NAME \"$VERSION_DEFAULT\" /* autogenerated */" + + while IFS= read -r -u3 item; do + COMP="#define $VERSION_NAME*" + if [[ $item == $COMP ]] ; then + LINE=$item + fi + done 3< "version.h" +fi + + +# avoid overwritting if contents are the same, as some systems rebuild on timestamp +LINE_ORIGINAL="none" +if test -f "version_auto.h"; then + LINE_ORIGINAL=$( "$VERSION_FILE" +fi From c2428c8faad735fd25f2f1ee2c406ecdac6a87ef Mon Sep 17 00:00:00 2001 From: bnnm Date: Thu, 12 Aug 2021 00:05:30 +0200 Subject: [PATCH 06/11] vs: remove faac includes for now --- cli/vgmstream_cli.vcxproj | 4 ++-- fb2k/foo_input_vgmstream.vcxproj | 8 ++++---- winamp/in_vgmstream.vcxproj | 4 ++-- xmplay/xmp-vgmstream.vcxproj | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cli/vgmstream_cli.vcxproj b/cli/vgmstream_cli.vcxproj index d1045157..d9b8145a 100644 --- a/cli/vgmstream_cli.vcxproj +++ b/cli/vgmstream_cli.vcxproj @@ -126,12 +126,12 @@ - + {10e6bfc6-1e5b-46e4-ba42-f04dfbd0abff} diff --git a/fb2k/foo_input_vgmstream.vcxproj b/fb2k/foo_input_vgmstream.vcxproj index 9d25ff51..a9589151 100644 --- a/fb2k/foo_input_vgmstream.vcxproj +++ b/fb2k/foo_input_vgmstream.vcxproj @@ -139,9 +139,12 @@ - + {622e8b19-8109-4717-bd4d-9657aa78363e} @@ -157,9 +160,6 @@ {ebfffb4e-261d-44d3-b89c-957b31a0bf9c} - - {86a064e2-c81b-4eee-8be0-a39a2e7c7c76} - {10e6bfc6-1e5b-46e4-ba42-f04dfbd0abff} diff --git a/winamp/in_vgmstream.vcxproj b/winamp/in_vgmstream.vcxproj index 1fece220..9db320c3 100644 --- a/winamp/in_vgmstream.vcxproj +++ b/winamp/in_vgmstream.vcxproj @@ -138,12 +138,12 @@ - + {10e6bfc6-1e5b-46e4-ba42-f04dfbd0abff} diff --git a/xmplay/xmp-vgmstream.vcxproj b/xmplay/xmp-vgmstream.vcxproj index edaa2890..e0087216 100644 --- a/xmplay/xmp-vgmstream.vcxproj +++ b/xmplay/xmp-vgmstream.vcxproj @@ -124,12 +124,12 @@ - + {10e6bfc6-1e5b-46e4-ba42-f04dfbd0abff} From 735948e947c7343b8d622174392bb9aac18e36d6 Mon Sep 17 00:00:00 2001 From: bnnm Date: Thu, 12 Aug 2021 00:05:53 +0200 Subject: [PATCH 07/11] gitattributes: cpp --- .gitattributes | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.gitattributes b/.gitattributes index f0c6b746..b316a22e 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,10 +1,13 @@ -# don't set for now (too many fixes at once) -#* text=auto -#*.c text=auto -#*.h text=auto -#* -text - -*.sh text eol=lf -*.bat text eol=crlf -*.vcxproj text eol=crlf -*.vcxproj.filters text eol=crlf +# don't set for now (too many fixes at once) +#* text=auto +#*.c text=auto +#*.h text=auto +#* -text + +*.cpp text eol=lf +*.cc text eol=lf + +*.sh text eol=lf +*.bat text eol=crlf +*.vcxproj text eol=crlf +*.vcxproj.filters text eol=crlf From 2084b225646324455eddd97cafc23758bbce7312 Mon Sep 17 00:00:00 2001 From: bnnm Date: Thu, 12 Aug 2021 00:09:33 +0200 Subject: [PATCH 08/11] build: remove some conditional includes --- audacious/plugin.cc | 2 - cli/vgmstream123.c | 4 +- cli/vgmstream_cli.c | 2 - fb2k/foo_vgmstream.cpp | 2 - winamp/in_vgmstream.c | 2 - xmplay/xmp_vgmstream.c | 1618 ++++++++++++++++++++-------------------- 6 files changed, 809 insertions(+), 821 deletions(-) diff --git a/audacious/plugin.cc b/audacious/plugin.cc index cb7b5a94..7a57eb40 100644 --- a/audacious/plugin.cc +++ b/audacious/plugin.cc @@ -22,9 +22,7 @@ extern "C" { #include "vfs.h" -#ifndef VGMSTREAM_VERSION #include "../version.h" -#endif #ifndef VGMSTREAM_VERSION #define VGMSTREAM_VERSION "(unknown-version)" #endif diff --git a/cli/vgmstream123.c b/cli/vgmstream123.c index 7c2b8447..d9185010 100644 --- a/cli/vgmstream123.c +++ b/cli/vgmstream123.c @@ -39,9 +39,7 @@ #include "../src/vgmstream.h" #include "../src/plugins.h" -#ifndef VGMSTREAM_VERSION -# include "../version.h" -#endif +#include "../version.h" #ifndef VGMSTREAM_VERSION # define VGMSTREAM_VERSION "(unknown version)" #endif diff --git a/cli/vgmstream_cli.c b/cli/vgmstream_cli.c index 8c8d9ddc..def2131d 100644 --- a/cli/vgmstream_cli.c +++ b/cli/vgmstream_cli.c @@ -16,9 +16,7 @@ #define STDOUT_FILENO 1 #endif -#ifndef VGMSTREAM_VERSION #include "../version.h" -#endif #ifndef VGMSTREAM_VERSION #define VGMSTREAM_VERSION "(unknown version)" #endif diff --git a/fb2k/foo_vgmstream.cpp b/fb2k/foo_vgmstream.cpp index 91d0d535..e83d62f7 100644 --- a/fb2k/foo_vgmstream.cpp +++ b/fb2k/foo_vgmstream.cpp @@ -19,9 +19,7 @@ extern "C" { #include "foo_vgmstream.h" #include "foo_filetypes.h" -#ifndef VGMSTREAM_VERSION #include "../version.h" -#endif #ifndef VGMSTREAM_VERSION #define PLUGIN_VERSION __DATE__ #else diff --git a/winamp/in_vgmstream.c b/winamp/in_vgmstream.c index 2d666e5f..9ba50284 100644 --- a/winamp/in_vgmstream.c +++ b/winamp/in_vgmstream.c @@ -3,9 +3,7 @@ */ #include "in_vgmstream.h" -#ifndef VGMSTREAM_VERSION #include "../version.h" -#endif #ifndef VGMSTREAM_VERSION #define VGMSTREAM_VERSION "(unknown version)" #endif diff --git a/xmplay/xmp_vgmstream.c b/xmplay/xmp_vgmstream.c index 3edc1af2..167e5ea3 100644 --- a/xmplay/xmp_vgmstream.c +++ b/xmplay/xmp_vgmstream.c @@ -1,810 +1,808 @@ -/** - * vgmstream for XMPlay - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "xmpin.h" -#include "../src/vgmstream.h" -#include "../src/plugins.h" - - -#ifndef VGMSTREAM_VERSION -#include "../version.h" -#endif -#ifndef VGMSTREAM_VERSION -#define VGMSTREAM_VERSION "(unknown version)" -#endif - -/* ************************************* */ - -#define SAMPLE_BUFFER_SIZE 1024 - -/* XMPlay extension list, only needed to associate extensions in Windows */ -/* todo: as of v3.8.2.17, any more than ~1000 will crash XMplay's file list screen (but not using the non-native Winamp plugin...) */ -#define EXTENSION_LIST_SIZE 1000 /* (0x2000 * 2) */ -#define XMPLAY_MAX_PATH 32768 - -/* XMPlay function library */ -static XMPFUNC_IN *xmpfin; -static XMPFUNC_MISC *xmpfmisc; -static XMPFUNC_FILE *xmpffile; - -char working_extension_list[EXTENSION_LIST_SIZE] = {0}; -char filepath[MAX_PATH]; - -/* plugin config */ -double fade_seconds = 10.0; -double fade_delay = 0.0; -double loop_count = 2.0; -int ignore_loop = 0; -int disable_subsongs = 1; -BOOL xmplay_doneloop = 0; - -/* plugin state */ -VGMSTREAM* vgmstream = NULL; -int decode_pos_samples; -int length_samples = 0; -int output_channels; -int current_subsong = 0; -INT16 sample_buffer[SAMPLE_BUFFER_SIZE * VGMSTREAM_MAX_CHANNELS]; - -//XMPFILE current_file = NULL; -//char current_fn[XMPLAY_MAX_PATH] = {0}; - -static int shownerror = 0; /* init error */ - -/* ************************************* */ - -/* a STREAMFILE that operates via XMPlay's XMPFUNC_FILE+XMPFILE */ -typedef struct _XMPLAY_STREAMFILE { - STREAMFILE sf; /* callbacks */ - XMPFILE infile; /* actual FILE */ - char name[PATH_LIMIT]; - off_t offset; /* current offset */ - int internal_xmpfile; /* infile was not supplied externally and can be closed */ -} XMPLAY_STREAMFILE; - -static STREAMFILE* open_xmplay_streamfile_by_xmpfile(XMPFILE file, const char* path, int internal); - -static size_t xmpsf_read(XMPLAY_STREAMFILE* sf, uint8_t* dest, off_t offset, size_t length) { - size_t read; - - if (sf->offset != offset) { - if (xmpffile->Seek(sf->infile, offset)) - sf->offset = offset; - else - sf->offset = xmpffile->Tell(sf->infile); - } - - read = xmpffile->Read(sf->infile, dest, length); - if (read > 0) - sf->offset += read; - - return read; -} - -static off_t xmpsf_get_size(XMPLAY_STREAMFILE* sf) { - return xmpffile->GetSize(sf->infile); -} - -static off_t xmpsf_get_offset(XMPLAY_STREAMFILE* sf) { - return xmpffile->Tell(sf->infile); -} - -static void xmpsf_get_name(XMPLAY_STREAMFILE* sf, char* buffer, size_t length) { - strncpy(buffer, sf->name, length); - buffer[length-1] = '\0'; -} - -static STREAMFILE *xmpsf_open(XMPLAY_STREAMFILE* sf, const char* const filename, size_t buffersize) { - XMPFILE newfile; - - if (!filename) - return NULL; - - newfile = xmpffile->Open(filename); - if (!newfile) return NULL; - - strncpy(filepath, filename, MAX_PATH); - filepath[MAX_PATH - 1] = 0x00; - - return open_xmplay_streamfile_by_xmpfile(newfile, filename, 1); /* internal XMPFILE */ -} - -static void xmpsf_close(XMPLAY_STREAMFILE* sf) { - /* Close XMPFILE, but only if we opened it (ex. for subfiles inside metas). - * Otherwise must be left open as other parts of XMPlay need it and would crash. */ - if (sf->internal_xmpfile) { - xmpffile->Close(sf->infile); - } - - free(sf); -} - -static STREAMFILE *open_xmplay_streamfile_by_xmpfile(XMPFILE infile, const char* path, int internal) { - XMPLAY_STREAMFILE* sf = calloc(1, sizeof(XMPLAY_STREAMFILE)); - if (!sf) return NULL; - - sf->sf.read = (void*)xmpsf_read; - sf->sf.get_size = (void*)xmpsf_get_size; - sf->sf.get_offset = (void*)xmpsf_get_offset; - sf->sf.get_name = (void*)xmpsf_get_name; - sf->sf.open = (void*)xmpsf_open; - sf->sf.close = (void*)xmpsf_close; - sf->infile = infile; - sf->offset = 0; - strncpy(sf->name, path, sizeof(sf->name)); - - sf->internal_xmpfile = internal; - - return &sf->sf; /* pointer to STREAMFILE start = rest of the custom data follows */ -} - -VGMSTREAM* init_vgmstream_xmplay(XMPFILE file, const char *path, int subsong) { - STREAMFILE* sf = NULL; - VGMSTREAM* vgmstream = NULL; - - sf = open_xmplay_streamfile_by_xmpfile(file, path, 0); /* external XMPFILE */ - if (!sf) return NULL; - - sf->stream_index = subsong; - vgmstream = init_vgmstream_from_STREAMFILE(sf); - if (!vgmstream) goto fail; - - return vgmstream; - -fail: - close_streamfile(sf); - return NULL; -} - -/* ************************************* */ - -static void apply_config(VGMSTREAM* vgmstream) { - vgmstream_cfg_t vcfg = {0}; - - vcfg.allow_play_forever = 0; - //vcfg.play_forever = loop_forever; - vcfg.loop_count = loop_count; - vcfg.fade_time = fade_seconds; - vcfg.fade_delay = fade_delay; - vcfg.ignore_loop = ignore_loop; - - vgmstream_apply_config(vgmstream, &vcfg); -} - - -/* get the tags as an array of "key\0value\0", NULL-terminated */ -static char *get_tags(VGMSTREAM * infostream) { - char* tags; - int pos = 0; - - tags = xmpfmisc->Alloc(1024); - memset(tags, 0x00, 1024); - - if (infostream->stream_name != NULL && strlen(infostream->stream_name) > 0) - { - memcpy(tags + pos, "title", 5); - pos += 6; - memcpy(tags + pos, infostream->stream_name, strlen(infostream->stream_name)); - pos += strlen(infostream->stream_name) + 1; - } - - char* end; - char* start = NULL; - int j = 2; - for (char* i = filepath+strlen(filepath); i > filepath; i--) - { - if ((*i == '\\') && (j == 1)) - { - start = i + 1; - j--; - break; - } - if ((*i == '\\') && (j == 2)) - { - end = i; - j--; - } - } - - //run some sanity checks - - int brace_curly = 0, brace_square = 0; - char check_ok = 0; - for (char* i = filepath; *i != 0; i++) - { - if (*i == '(') - brace_curly++; - if (*i == ')') - brace_curly--; - if (*i == '[') - brace_square++; - if (*i == ']') - brace_square--; - if (brace_curly > 1 || brace_curly < -1 || brace_square > 1 || brace_square < -1) - break; - } - - if (brace_square == 0 && brace_curly == 0) - check_ok = 1; - - if (start != NULL && strstr(filepath, "\\VGMPP\\") != NULL && check_ok == 1 && strchr(start, '(') != NULL) - { - char tagline[1024]; - memset(tagline, 0x00, sizeof(tagline)); - strncpy(tagline, start, end - start); - - char* alttitle_st; - char* alttitle_ed; - char* album_st; - char* album_ed; - char* company_st; - char* company_ed; - char* company2_st; - char* company2_ed; - char* date_st; - char* date_ed; - char* platform_st; - char* platform_ed; - - if (strchr(tagline, '[') != NULL) //either alternative title or platform usually - { - alttitle_st = strchr(tagline, '[') + 1; - alttitle_ed = strchr(alttitle_st, ']'); - if (strchr(alttitle_st, '[') != NULL && strchr(alttitle_st, '[') > strchr(alttitle_st, '(')) //both might be present actually - { - platform_st = strchr(alttitle_st, '[') + 1; - platform_ed = strchr(alttitle_ed + 1, ']'); - } - else - { - platform_st = NULL; - platform_ed = NULL; - } - } - else - { - platform_st = NULL; - platform_ed = NULL; - alttitle_st = NULL; - alttitle_ed = NULL; - } - - album_st = tagline; - - if (strchr(tagline, '(') < alttitle_st && alttitle_st != NULL) //square braces after curly braces -- platform - { - platform_st = alttitle_st; - platform_ed = alttitle_ed; - alttitle_st = NULL; - alttitle_ed = NULL; - album_ed = strchr(tagline, '('); //get normal title for now - } - else if (alttitle_st != NULL) - album_ed = strchr(tagline, '['); - else - album_ed = strchr(tagline, '('); - - date_st = strchr(album_ed, '(') + 1; //first string in curly braces is usualy release date, I have one package with platform name there - if (date_st == NULL) - date_ed = NULL; - if (date_st[0] >= 0x30 && date_st[0] <= 0x39 && date_st[1] >= 0x30 && date_st[1] <= 0x39) //check if it contains 2 digits - { - date_ed = strchr(date_st, ')'); - } - else //platform? - { - platform_st = date_st; - platform_ed = strchr(date_st, ')'); - date_st = strchr(platform_ed, '(') + 1; - date_ed = strchr(date_st, ')'); - } - - company_st = strchr(date_ed, '(') + 1; //company name follows date - if (company_st != NULL) - { - company_ed = strchr(company_st, ')'); - if (strchr(company_ed, '(') != NULL) - { - company2_st = strchr(company_ed, '(') + 1; - company2_ed = strchr(company2_st, ')'); - } - else - { - company2_st = NULL; - company2_ed = NULL; - } - } - else - { - company_st = NULL; - company_ed = NULL; - company2_st = NULL; - company2_ed = NULL; - } - - if (alttitle_st != NULL) //prefer alternative title, which is usually japanese - { - memcpy(tags + pos, "album", 5); - pos += 6; - memcpy(tags + pos, alttitle_st, alttitle_ed - alttitle_st); - pos += alttitle_ed - alttitle_st + 1; - } - else - { - memcpy(tags + pos, "album", 5); - pos += 6; - memcpy(tags + pos, album_st, album_ed - album_st); - pos += album_ed - album_st + 1; - } - - if (date_st != NULL) - { - memcpy(tags + pos, "date", 4); - pos += 5; - memcpy(tags + pos, date_st, date_ed - date_st); - pos += date_ed - date_st + 1; - } - - if (date_st != NULL) - { - memcpy(tags + pos, "genre", 5); - pos += 6; - memcpy(tags + pos, platform_st, platform_ed - platform_st); - pos += platform_ed - platform_st + 1; - } - - if (company_st != NULL) - { - char combuf[256]; - memset(combuf, 0x00, sizeof(combuf)); - char tmp[128]; - memset(tmp, 0x00, sizeof(tmp)); - memcpy(tmp, company_st, company_ed - company_st); - if (company2_st != NULL) - { - char tmp2[128]; - memset(tmp2, 0x00, sizeof(tmp2)); - memcpy(tmp2, company2_st, company2_ed - company2_st); - sprintf(combuf, "\r\n\r\nDeveloper\t%s\r\nPublisher\t%s", tmp, tmp2); - } - else - sprintf(combuf, "\r\n\r\nDeveloper\t%s", tmp); - - memcpy(tags + pos, "comment", 7); - pos += 8; - memcpy(tags + pos, combuf, strlen(combuf)); - pos += strlen(combuf) + 1; - } - } - return tags; /* assuming XMPlay free()s this, since it Alloc()s it */ -} - -/* Adds ext to XMPlay's extension list. */ -static int add_extension(int length, char * dst, const char * ext) { - int ext_len; - int i; - - if (length <= 1) - return 0; - - ext_len = strlen(ext); - - /* check if end reached or not enough room to add */ - if (ext_len+2 > length-2) { - dst[0]='\0'; - return 0; - } - - /* copy new extension + null terminate */ - for (i=0; i < ext_len; i++) - dst[i] = ext[i]; - dst[i]='/'; - dst[i+1]='\0'; - return i+1; -} - -/* Creates XMPlay's extension list, a single string with 2 nulls. - * Extensions must be in this format: "Description\0extension1/.../extensionN" */ -static void build_extension_list() { - const char ** ext_list; - size_t ext_list_len; - int i, written; - - written = sprintf(working_extension_list, "%s%c", "vgmstream files",'\0'); - - ext_list = vgmstream_get_formats(&ext_list_len); - - for (i=0; i < ext_list_len; i++) { - written += add_extension(EXTENSION_LIST_SIZE-written, working_extension_list + written, ext_list[i]); - } - working_extension_list[written-1] = '\0'; /* remove last "/" */ -} - -/* ************************************* */ - -/* info for the "about" button in plugin options */ -void WINAPI xmplay_About(HWND win) { - MessageBox(win, - "vgmstream plugin " VGMSTREAM_VERSION " " __DATE__ "\n" - "by hcs, FastElbja, manakoAT, bxaimc, snakemeat, soneek, kode54, bnnm and many others\n" - "\n" - "XMPlay plugin by unknownfile, PSXGamerPro1, kode54\n" - "\n" - "https://github.com/kode54/vgmstream/\n" - "https://sourceforge.net/projects/vgmstream/ (original)" - ,"about xmp-vgmstream",MB_OK); -} - -#if 0 -/* present config options to user (OPTIONAL) */ -void WINAPI xmplay_Config(HWND win) { - /* defined in resource.rc */ - DialogBox(input_module.hDllInstance, (const char *)IDD_CONFIG, win, configDlgProc); -} -#endif - -/* quick check if a file is playable by this plugin */ -BOOL WINAPI xmplay_CheckFile(const char *filename, XMPFILE file) { - VGMSTREAM* infostream = NULL; - if (file) - infostream = init_vgmstream_xmplay(file, filename, 0); - else - infostream = init_vgmstream(filename); //TODO: unicode problems? - if (!infostream) - return FALSE; - - close_vgmstream(infostream); - - return TRUE; -} - -/* update info from a file, returning the number of subsongs */ -DWORD WINAPI xmplay_GetFileInfo(const char *filename, XMPFILE file, float **length, char **tags) { - VGMSTREAM* infostream; - int subsong_count; - - if (file) - infostream = init_vgmstream_xmplay(file, filename, 0); - else - infostream = init_vgmstream(filename); //TODO: unicode problems? - if (!infostream) - return 0; - - apply_config(infostream); - - //vgmstream_mixing_autodownmix(infostream, downmix_channels); - vgmstream_mixing_enable(infostream, 0, NULL, NULL); - - if (length && infostream->sample_rate) { - int length_samples = vgmstream_get_samples(infostream); - float *lens = (float*)xmpfmisc->Alloc(sizeof(float)); - lens[0] = (float)length_samples / (float)infostream->sample_rate; - *length = lens; - } - - subsong_count = infostream->num_streams; - if (disable_subsongs || subsong_count == 0) - subsong_count = 1; - - *tags = get_tags(infostream); - close_vgmstream(infostream); - - return subsong_count; -} - -/* open a file for playback, returning: 0=failed, 1=success, 2=success and XMPlay can close the file */ -DWORD WINAPI xmplay_Open(const char *filename, XMPFILE file) { - if (file) - vgmstream = init_vgmstream_xmplay(file, filename, current_subsong+1); - else - vgmstream = init_vgmstream(filename); - if (!vgmstream) - return 0; - - apply_config(vgmstream); - - //vgmstream_mixing_autodownmix(vgmstream, downmix_channels); - vgmstream_mixing_enable(vgmstream, SAMPLE_BUFFER_SIZE, NULL /*&input_channels*/, &output_channels); - - decode_pos_samples = 0; - length_samples = vgmstream_get_samples(vgmstream); - - //strncpy(current_fn,filename,XMPLAY_MAX_PATH); - //current_file = file; - //current_subsong = 0; - - - if (length_samples) { - float length = (float)length_samples / (float)vgmstream->sample_rate; - xmpfin->SetLength(length, TRUE); - } - - return 1; -} - -/* close the playback file */ -void WINAPI xmplay_Close() { - close_vgmstream(vgmstream); - vgmstream = NULL; -} - -/* set the sample format */ -void WINAPI xmplay_SetFormat(XMPFORMAT *form) { - form->res = 16 / 8; /* PCM 16 */ - form->chan = output_channels; - form->rate = vgmstream->sample_rate; -} - -/* get tags, return NULL to delay title update (OPTIONAL) */ -char * WINAPI xmplay_GetTags() { - return get_tags(vgmstream); -} - -/* main panel info text (short file info) */ -void WINAPI xmplay_GetInfoText(char* format, char* length) { - int rate, samples, bps; - char fmt[128]; - int t, tmin, tsec; - - if (!format) - return; - if (!vgmstream) - return; - - rate = vgmstream->sample_rate; - samples = vgmstream->num_samples; - bps = get_vgmstream_average_bitrate(vgmstream) / 1000; - get_vgmstream_coding_description(vgmstream, fmt, sizeof(fmt)); - if (strcmp(fmt, "FFmpeg") == 0) - { - char buffer[1024]; - buffer[0] = '\0'; - describe_vgmstream(vgmstream, buffer, sizeof(buffer)); - char* enc_tmp = strstr(buffer, "encoding: ") + 10; - char* enc_end = strstr(enc_tmp, "\n"); - int len = (int)enc_end - (int)enc_tmp; - - memset(fmt, 0x00, sizeof(fmt)); - strncpy(fmt, enc_tmp, len); - } - - t = samples / rate; - tmin = t / 60; - tsec = t % 60; - - sprintf(format, "%s", fmt); - sprintf(length, "%d:%02d - %dKb/s - %dHz", tmin, tsec, bps, rate); -} - -/* info for the "General" window/tab (buf is ~40K) */ -void WINAPI xmplay_GetGeneralInfo(char* buf) { - int i; - char description[1024]; - - if (!buf) - return; - if (!vgmstream) - return; - - description[0] = '\0'; - describe_vgmstream(vgmstream,description,sizeof(description)); - - /* tags are divided with a tab and lines with carriage return so we'll do some guetto fixin' */ - int tag_done = 0; - description[0] -= 32; //Replace small letter with capital for consistency with XMPlay's output - for (i = 0; i < 1024; i++) { - if (description[i] == '\0') - break; - - if (description[i] == ':' && !tag_done) { /* to ignore multiple ':' in a line*/ - description[i] = ' '; - description[i+1] = '\t'; - tag_done = 1; - } - - if (description[i] == '\n') { - description[i] = '\r'; - if (description[i+1]) - description[i+1] -= 32; //Replace small letter with capital for consistency with XMPlay's output - tag_done = 0; - } - } - - sprintf(buf,"%s", description); -} - -/* get the seeking granularity in seconds */ -double WINAPI xmplay_GetGranularity() { - return 0.001; /* can seek in milliseconds */ -} - -/* seek to a position (in granularity units), return new position or -1 = failed */ -double WINAPI xmplay_SetPosition(DWORD pos) { - double cpos; - int seek_sample = pos * xmplay_GetGranularity() * vgmstream->sample_rate; - - if (pos == XMPIN_POS_AUTOLOOP || pos == XMPIN_POS_LOOP) - xmplay_doneloop = 1; - -#if 0 - /* set a subsong */ - if (!disable_subsongs && (pos & XMPIN_POS_SUBSONG)) { - int new_subsong = LOWORD(pos); - - /* "single subsong mode (don't show info on other subsongs)" */ - if (pos & XMPIN_POS_SUBSONG1) { - // ??? - } - - if (new_subsong && new_subsong != current_subsong) { /* todo implicit? */ - if (current_file) - return -1; - - vgmstream = init_vgmstream_xmplay(current_file, current_fn, current_subsong+1); - if (!vgmstream) return -1; - - current_subsong = new_subsong; - return 0.0; - } - } -#endif - - seek_vgmstream(vgmstream, seek_sample); - - decode_pos_samples = seek_sample; - - cpos = (double)decode_pos_samples / vgmstream->sample_rate; - return cpos; -} - -/* decode some sample data */ -DWORD WINAPI xmplay_Process(float* buf, DWORD bufsize) { - int32_t i, done, samples_to_do; - BOOL do_loop = xmpfin->GetLooping(); - float *sbuf = buf; - - - bufsize /= output_channels; - - samples_to_do = do_loop ? bufsize : length_samples - decode_pos_samples; - if (samples_to_do > bufsize) - samples_to_do = bufsize; - - /* decode */ - done = 0; - while (done < samples_to_do) { - int to_do = SAMPLE_BUFFER_SIZE; - if (to_do > samples_to_do - done) - to_do = samples_to_do - done; - - render_vgmstream(sample_buffer, to_do, vgmstream); - - for (i = 0; i < to_do * output_channels; i++) { - *sbuf++ = sample_buffer[i] * 1.0f / 32768.0f; - } - - done += to_do; - } - - sbuf = buf; - - decode_pos_samples += done; - - return done * output_channels; -} - -static DWORD WINAPI xmplay_GetSubSongs(float *length) { - int subsong_count; - - if (!vgmstream) - return 0; - - subsong_count = vgmstream->num_streams; - if (disable_subsongs || subsong_count == 0) - subsong_count = 1; - - /* get times for all subsongs */ - //todo request updating playlist update every subsong change instead? - { - int stream_length_samples; - - /* not good for vgmstream as would mean re-parsing many times */ - //int i; - //for (i = 0; i < subsong_count; i++) { - // float subsong_length = ... - // *length += subsong_length; - //} - - /* simply use the current length */ //todo just use 0? - length_samples = vgmstream_get_samples(vgmstream); - *length = (float)length_samples / (float)vgmstream->sample_rate; - } - - return subsong_count; -} - -/* *********************************** */ - -/* main plugin def, see xmpin.h */ -XMPIN vgmstream_xmpin = { - XMPIN_FLAG_CANSTREAM, - "vgmstream for XMPlay", - working_extension_list, - xmplay_About, - NULL,//XMP_Config - xmplay_CheckFile, - xmplay_GetFileInfo, - xmplay_Open, - xmplay_Close, - NULL, - xmplay_SetFormat, - xmplay_GetTags, //(OPTIONAL) --actually mandatory - xmplay_GetInfoText, - xmplay_GetGeneralInfo, - NULL,//GetMessage - text for the "Message" tab window/tab (OPTIONAL) - xmplay_SetPosition, - xmplay_GetGranularity, - NULL, - xmplay_Process, - NULL, - NULL, - xmplay_GetSubSongs, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, - NULL, -}; - -/* get the plugin's XMPIN interface */ -__declspec(dllexport) XMPIN* WINAPI XMPIN_GetInterface(UINT32 face, InterfaceProc faceproc) { - if (face != XMPIN_FACE) { - // unsupported version - if (face < XMPIN_FACE && !shownerror) { - MessageBox(0, - "The xmp-vgmstream plugin requires XMPlay 3.8 or above.\n\n" - "Please update at:\n" - "http://www.un4seen.com/xmplay.html\n" - "http://www.un4seen.com/stuff/xmplay.exe", 0, MB_ICONEXCLAMATION); - shownerror = 1; - } - return NULL; - } - - xmpfin = (XMPFUNC_IN*)faceproc(XMPFUNC_IN_FACE); - xmpfmisc = (XMPFUNC_MISC*)faceproc(XMPFUNC_MISC_FACE); - xmpffile = (XMPFUNC_FILE*)faceproc(XMPFUNC_FILE_FACE); - - build_extension_list(); - - return &vgmstream_xmpin; -} - -#if 0 -// needed? -BOOL WINAPI DllMain(HINSTANCE hDLL, DWORD reason, LPVOID reserved) { - switch (reason) { - case DLL_PROCESS_ATTACH: - DisableThreadLibraryCalls(hDLL); - break; - } - return TRUE; -} -#endif +/** + * vgmstream for XMPlay + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xmpin.h" +#include "../src/vgmstream.h" +#include "../src/plugins.h" + + +#include "../version.h" +#ifndef VGMSTREAM_VERSION +#define VGMSTREAM_VERSION "(unknown version)" +#endif + +/* ************************************* */ + +#define SAMPLE_BUFFER_SIZE 1024 + +/* XMPlay extension list, only needed to associate extensions in Windows */ +/* todo: as of v3.8.2.17, any more than ~1000 will crash XMplay's file list screen (but not using the non-native Winamp plugin...) */ +#define EXTENSION_LIST_SIZE 1000 /* (0x2000 * 2) */ +#define XMPLAY_MAX_PATH 32768 + +/* XMPlay function library */ +static XMPFUNC_IN *xmpfin; +static XMPFUNC_MISC *xmpfmisc; +static XMPFUNC_FILE *xmpffile; + +char working_extension_list[EXTENSION_LIST_SIZE] = {0}; +char filepath[MAX_PATH]; + +/* plugin config */ +double fade_seconds = 10.0; +double fade_delay = 0.0; +double loop_count = 2.0; +int ignore_loop = 0; +int disable_subsongs = 1; +BOOL xmplay_doneloop = 0; + +/* plugin state */ +VGMSTREAM* vgmstream = NULL; +int decode_pos_samples; +int length_samples = 0; +int output_channels; +int current_subsong = 0; +INT16 sample_buffer[SAMPLE_BUFFER_SIZE * VGMSTREAM_MAX_CHANNELS]; + +//XMPFILE current_file = NULL; +//char current_fn[XMPLAY_MAX_PATH] = {0}; + +static int shownerror = 0; /* init error */ + +/* ************************************* */ + +/* a STREAMFILE that operates via XMPlay's XMPFUNC_FILE+XMPFILE */ +typedef struct _XMPLAY_STREAMFILE { + STREAMFILE sf; /* callbacks */ + XMPFILE infile; /* actual FILE */ + char name[PATH_LIMIT]; + off_t offset; /* current offset */ + int internal_xmpfile; /* infile was not supplied externally and can be closed */ +} XMPLAY_STREAMFILE; + +static STREAMFILE* open_xmplay_streamfile_by_xmpfile(XMPFILE file, const char* path, int internal); + +static size_t xmpsf_read(XMPLAY_STREAMFILE* sf, uint8_t* dest, off_t offset, size_t length) { + size_t read; + + if (sf->offset != offset) { + if (xmpffile->Seek(sf->infile, offset)) + sf->offset = offset; + else + sf->offset = xmpffile->Tell(sf->infile); + } + + read = xmpffile->Read(sf->infile, dest, length); + if (read > 0) + sf->offset += read; + + return read; +} + +static off_t xmpsf_get_size(XMPLAY_STREAMFILE* sf) { + return xmpffile->GetSize(sf->infile); +} + +static off_t xmpsf_get_offset(XMPLAY_STREAMFILE* sf) { + return xmpffile->Tell(sf->infile); +} + +static void xmpsf_get_name(XMPLAY_STREAMFILE* sf, char* buffer, size_t length) { + strncpy(buffer, sf->name, length); + buffer[length-1] = '\0'; +} + +static STREAMFILE *xmpsf_open(XMPLAY_STREAMFILE* sf, const char* const filename, size_t buffersize) { + XMPFILE newfile; + + if (!filename) + return NULL; + + newfile = xmpffile->Open(filename); + if (!newfile) return NULL; + + strncpy(filepath, filename, MAX_PATH); + filepath[MAX_PATH - 1] = 0x00; + + return open_xmplay_streamfile_by_xmpfile(newfile, filename, 1); /* internal XMPFILE */ +} + +static void xmpsf_close(XMPLAY_STREAMFILE* sf) { + /* Close XMPFILE, but only if we opened it (ex. for subfiles inside metas). + * Otherwise must be left open as other parts of XMPlay need it and would crash. */ + if (sf->internal_xmpfile) { + xmpffile->Close(sf->infile); + } + + free(sf); +} + +static STREAMFILE *open_xmplay_streamfile_by_xmpfile(XMPFILE infile, const char* path, int internal) { + XMPLAY_STREAMFILE* sf = calloc(1, sizeof(XMPLAY_STREAMFILE)); + if (!sf) return NULL; + + sf->sf.read = (void*)xmpsf_read; + sf->sf.get_size = (void*)xmpsf_get_size; + sf->sf.get_offset = (void*)xmpsf_get_offset; + sf->sf.get_name = (void*)xmpsf_get_name; + sf->sf.open = (void*)xmpsf_open; + sf->sf.close = (void*)xmpsf_close; + sf->infile = infile; + sf->offset = 0; + strncpy(sf->name, path, sizeof(sf->name)); + + sf->internal_xmpfile = internal; + + return &sf->sf; /* pointer to STREAMFILE start = rest of the custom data follows */ +} + +VGMSTREAM* init_vgmstream_xmplay(XMPFILE file, const char *path, int subsong) { + STREAMFILE* sf = NULL; + VGMSTREAM* vgmstream = NULL; + + sf = open_xmplay_streamfile_by_xmpfile(file, path, 0); /* external XMPFILE */ + if (!sf) return NULL; + + sf->stream_index = subsong; + vgmstream = init_vgmstream_from_STREAMFILE(sf); + if (!vgmstream) goto fail; + + return vgmstream; + +fail: + close_streamfile(sf); + return NULL; +} + +/* ************************************* */ + +static void apply_config(VGMSTREAM* vgmstream) { + vgmstream_cfg_t vcfg = {0}; + + vcfg.allow_play_forever = 0; + //vcfg.play_forever = loop_forever; + vcfg.loop_count = loop_count; + vcfg.fade_time = fade_seconds; + vcfg.fade_delay = fade_delay; + vcfg.ignore_loop = ignore_loop; + + vgmstream_apply_config(vgmstream, &vcfg); +} + + +/* get the tags as an array of "key\0value\0", NULL-terminated */ +static char *get_tags(VGMSTREAM * infostream) { + char* tags; + int pos = 0; + + tags = xmpfmisc->Alloc(1024); + memset(tags, 0x00, 1024); + + if (infostream->stream_name != NULL && strlen(infostream->stream_name) > 0) + { + memcpy(tags + pos, "title", 5); + pos += 6; + memcpy(tags + pos, infostream->stream_name, strlen(infostream->stream_name)); + pos += strlen(infostream->stream_name) + 1; + } + + char* end; + char* start = NULL; + int j = 2; + for (char* i = filepath+strlen(filepath); i > filepath; i--) + { + if ((*i == '\\') && (j == 1)) + { + start = i + 1; + j--; + break; + } + if ((*i == '\\') && (j == 2)) + { + end = i; + j--; + } + } + + //run some sanity checks + + int brace_curly = 0, brace_square = 0; + char check_ok = 0; + for (char* i = filepath; *i != 0; i++) + { + if (*i == '(') + brace_curly++; + if (*i == ')') + brace_curly--; + if (*i == '[') + brace_square++; + if (*i == ']') + brace_square--; + if (brace_curly > 1 || brace_curly < -1 || brace_square > 1 || brace_square < -1) + break; + } + + if (brace_square == 0 && brace_curly == 0) + check_ok = 1; + + if (start != NULL && strstr(filepath, "\\VGMPP\\") != NULL && check_ok == 1 && strchr(start, '(') != NULL) + { + char tagline[1024]; + memset(tagline, 0x00, sizeof(tagline)); + strncpy(tagline, start, end - start); + + char* alttitle_st; + char* alttitle_ed; + char* album_st; + char* album_ed; + char* company_st; + char* company_ed; + char* company2_st; + char* company2_ed; + char* date_st; + char* date_ed; + char* platform_st; + char* platform_ed; + + if (strchr(tagline, '[') != NULL) //either alternative title or platform usually + { + alttitle_st = strchr(tagline, '[') + 1; + alttitle_ed = strchr(alttitle_st, ']'); + if (strchr(alttitle_st, '[') != NULL && strchr(alttitle_st, '[') > strchr(alttitle_st, '(')) //both might be present actually + { + platform_st = strchr(alttitle_st, '[') + 1; + platform_ed = strchr(alttitle_ed + 1, ']'); + } + else + { + platform_st = NULL; + platform_ed = NULL; + } + } + else + { + platform_st = NULL; + platform_ed = NULL; + alttitle_st = NULL; + alttitle_ed = NULL; + } + + album_st = tagline; + + if (strchr(tagline, '(') < alttitle_st && alttitle_st != NULL) //square braces after curly braces -- platform + { + platform_st = alttitle_st; + platform_ed = alttitle_ed; + alttitle_st = NULL; + alttitle_ed = NULL; + album_ed = strchr(tagline, '('); //get normal title for now + } + else if (alttitle_st != NULL) + album_ed = strchr(tagline, '['); + else + album_ed = strchr(tagline, '('); + + date_st = strchr(album_ed, '(') + 1; //first string in curly braces is usualy release date, I have one package with platform name there + if (date_st == NULL) + date_ed = NULL; + if (date_st[0] >= 0x30 && date_st[0] <= 0x39 && date_st[1] >= 0x30 && date_st[1] <= 0x39) //check if it contains 2 digits + { + date_ed = strchr(date_st, ')'); + } + else //platform? + { + platform_st = date_st; + platform_ed = strchr(date_st, ')'); + date_st = strchr(platform_ed, '(') + 1; + date_ed = strchr(date_st, ')'); + } + + company_st = strchr(date_ed, '(') + 1; //company name follows date + if (company_st != NULL) + { + company_ed = strchr(company_st, ')'); + if (strchr(company_ed, '(') != NULL) + { + company2_st = strchr(company_ed, '(') + 1; + company2_ed = strchr(company2_st, ')'); + } + else + { + company2_st = NULL; + company2_ed = NULL; + } + } + else + { + company_st = NULL; + company_ed = NULL; + company2_st = NULL; + company2_ed = NULL; + } + + if (alttitle_st != NULL) //prefer alternative title, which is usually japanese + { + memcpy(tags + pos, "album", 5); + pos += 6; + memcpy(tags + pos, alttitle_st, alttitle_ed - alttitle_st); + pos += alttitle_ed - alttitle_st + 1; + } + else + { + memcpy(tags + pos, "album", 5); + pos += 6; + memcpy(tags + pos, album_st, album_ed - album_st); + pos += album_ed - album_st + 1; + } + + if (date_st != NULL) + { + memcpy(tags + pos, "date", 4); + pos += 5; + memcpy(tags + pos, date_st, date_ed - date_st); + pos += date_ed - date_st + 1; + } + + if (date_st != NULL) + { + memcpy(tags + pos, "genre", 5); + pos += 6; + memcpy(tags + pos, platform_st, platform_ed - platform_st); + pos += platform_ed - platform_st + 1; + } + + if (company_st != NULL) + { + char combuf[256]; + memset(combuf, 0x00, sizeof(combuf)); + char tmp[128]; + memset(tmp, 0x00, sizeof(tmp)); + memcpy(tmp, company_st, company_ed - company_st); + if (company2_st != NULL) + { + char tmp2[128]; + memset(tmp2, 0x00, sizeof(tmp2)); + memcpy(tmp2, company2_st, company2_ed - company2_st); + sprintf(combuf, "\r\n\r\nDeveloper\t%s\r\nPublisher\t%s", tmp, tmp2); + } + else + sprintf(combuf, "\r\n\r\nDeveloper\t%s", tmp); + + memcpy(tags + pos, "comment", 7); + pos += 8; + memcpy(tags + pos, combuf, strlen(combuf)); + pos += strlen(combuf) + 1; + } + } + return tags; /* assuming XMPlay free()s this, since it Alloc()s it */ +} + +/* Adds ext to XMPlay's extension list. */ +static int add_extension(int length, char * dst, const char * ext) { + int ext_len; + int i; + + if (length <= 1) + return 0; + + ext_len = strlen(ext); + + /* check if end reached or not enough room to add */ + if (ext_len+2 > length-2) { + dst[0]='\0'; + return 0; + } + + /* copy new extension + null terminate */ + for (i=0; i < ext_len; i++) + dst[i] = ext[i]; + dst[i]='/'; + dst[i+1]='\0'; + return i+1; +} + +/* Creates XMPlay's extension list, a single string with 2 nulls. + * Extensions must be in this format: "Description\0extension1/.../extensionN" */ +static void build_extension_list() { + const char ** ext_list; + size_t ext_list_len; + int i, written; + + written = sprintf(working_extension_list, "%s%c", "vgmstream files",'\0'); + + ext_list = vgmstream_get_formats(&ext_list_len); + + for (i=0; i < ext_list_len; i++) { + written += add_extension(EXTENSION_LIST_SIZE-written, working_extension_list + written, ext_list[i]); + } + working_extension_list[written-1] = '\0'; /* remove last "/" */ +} + +/* ************************************* */ + +/* info for the "about" button in plugin options */ +void WINAPI xmplay_About(HWND win) { + MessageBox(win, + "vgmstream plugin " VGMSTREAM_VERSION " " __DATE__ "\n" + "by hcs, FastElbja, manakoAT, bxaimc, snakemeat, soneek, kode54, bnnm and many others\n" + "\n" + "XMPlay plugin by unknownfile, PSXGamerPro1, kode54\n" + "\n" + "https://github.com/kode54/vgmstream/\n" + "https://sourceforge.net/projects/vgmstream/ (original)" + ,"about xmp-vgmstream",MB_OK); +} + +#if 0 +/* present config options to user (OPTIONAL) */ +void WINAPI xmplay_Config(HWND win) { + /* defined in resource.rc */ + DialogBox(input_module.hDllInstance, (const char *)IDD_CONFIG, win, configDlgProc); +} +#endif + +/* quick check if a file is playable by this plugin */ +BOOL WINAPI xmplay_CheckFile(const char *filename, XMPFILE file) { + VGMSTREAM* infostream = NULL; + if (file) + infostream = init_vgmstream_xmplay(file, filename, 0); + else + infostream = init_vgmstream(filename); //TODO: unicode problems? + if (!infostream) + return FALSE; + + close_vgmstream(infostream); + + return TRUE; +} + +/* update info from a file, returning the number of subsongs */ +DWORD WINAPI xmplay_GetFileInfo(const char *filename, XMPFILE file, float **length, char **tags) { + VGMSTREAM* infostream; + int subsong_count; + + if (file) + infostream = init_vgmstream_xmplay(file, filename, 0); + else + infostream = init_vgmstream(filename); //TODO: unicode problems? + if (!infostream) + return 0; + + apply_config(infostream); + + //vgmstream_mixing_autodownmix(infostream, downmix_channels); + vgmstream_mixing_enable(infostream, 0, NULL, NULL); + + if (length && infostream->sample_rate) { + int length_samples = vgmstream_get_samples(infostream); + float *lens = (float*)xmpfmisc->Alloc(sizeof(float)); + lens[0] = (float)length_samples / (float)infostream->sample_rate; + *length = lens; + } + + subsong_count = infostream->num_streams; + if (disable_subsongs || subsong_count == 0) + subsong_count = 1; + + *tags = get_tags(infostream); + close_vgmstream(infostream); + + return subsong_count; +} + +/* open a file for playback, returning: 0=failed, 1=success, 2=success and XMPlay can close the file */ +DWORD WINAPI xmplay_Open(const char *filename, XMPFILE file) { + if (file) + vgmstream = init_vgmstream_xmplay(file, filename, current_subsong+1); + else + vgmstream = init_vgmstream(filename); + if (!vgmstream) + return 0; + + apply_config(vgmstream); + + //vgmstream_mixing_autodownmix(vgmstream, downmix_channels); + vgmstream_mixing_enable(vgmstream, SAMPLE_BUFFER_SIZE, NULL /*&input_channels*/, &output_channels); + + decode_pos_samples = 0; + length_samples = vgmstream_get_samples(vgmstream); + + //strncpy(current_fn,filename,XMPLAY_MAX_PATH); + //current_file = file; + //current_subsong = 0; + + + if (length_samples) { + float length = (float)length_samples / (float)vgmstream->sample_rate; + xmpfin->SetLength(length, TRUE); + } + + return 1; +} + +/* close the playback file */ +void WINAPI xmplay_Close() { + close_vgmstream(vgmstream); + vgmstream = NULL; +} + +/* set the sample format */ +void WINAPI xmplay_SetFormat(XMPFORMAT *form) { + form->res = 16 / 8; /* PCM 16 */ + form->chan = output_channels; + form->rate = vgmstream->sample_rate; +} + +/* get tags, return NULL to delay title update (OPTIONAL) */ +char * WINAPI xmplay_GetTags() { + return get_tags(vgmstream); +} + +/* main panel info text (short file info) */ +void WINAPI xmplay_GetInfoText(char* format, char* length) { + int rate, samples, bps; + char fmt[128]; + int t, tmin, tsec; + + if (!format) + return; + if (!vgmstream) + return; + + rate = vgmstream->sample_rate; + samples = vgmstream->num_samples; + bps = get_vgmstream_average_bitrate(vgmstream) / 1000; + get_vgmstream_coding_description(vgmstream, fmt, sizeof(fmt)); + if (strcmp(fmt, "FFmpeg") == 0) + { + char buffer[1024]; + buffer[0] = '\0'; + describe_vgmstream(vgmstream, buffer, sizeof(buffer)); + char* enc_tmp = strstr(buffer, "encoding: ") + 10; + char* enc_end = strstr(enc_tmp, "\n"); + int len = (int)enc_end - (int)enc_tmp; + + memset(fmt, 0x00, sizeof(fmt)); + strncpy(fmt, enc_tmp, len); + } + + t = samples / rate; + tmin = t / 60; + tsec = t % 60; + + sprintf(format, "%s", fmt); + sprintf(length, "%d:%02d - %dKb/s - %dHz", tmin, tsec, bps, rate); +} + +/* info for the "General" window/tab (buf is ~40K) */ +void WINAPI xmplay_GetGeneralInfo(char* buf) { + int i; + char description[1024]; + + if (!buf) + return; + if (!vgmstream) + return; + + description[0] = '\0'; + describe_vgmstream(vgmstream,description,sizeof(description)); + + /* tags are divided with a tab and lines with carriage return so we'll do some guetto fixin' */ + int tag_done = 0; + description[0] -= 32; //Replace small letter with capital for consistency with XMPlay's output + for (i = 0; i < 1024; i++) { + if (description[i] == '\0') + break; + + if (description[i] == ':' && !tag_done) { /* to ignore multiple ':' in a line*/ + description[i] = ' '; + description[i+1] = '\t'; + tag_done = 1; + } + + if (description[i] == '\n') { + description[i] = '\r'; + if (description[i+1]) + description[i+1] -= 32; //Replace small letter with capital for consistency with XMPlay's output + tag_done = 0; + } + } + + sprintf(buf,"%s", description); +} + +/* get the seeking granularity in seconds */ +double WINAPI xmplay_GetGranularity() { + return 0.001; /* can seek in milliseconds */ +} + +/* seek to a position (in granularity units), return new position or -1 = failed */ +double WINAPI xmplay_SetPosition(DWORD pos) { + double cpos; + int seek_sample = pos * xmplay_GetGranularity() * vgmstream->sample_rate; + + if (pos == XMPIN_POS_AUTOLOOP || pos == XMPIN_POS_LOOP) + xmplay_doneloop = 1; + +#if 0 + /* set a subsong */ + if (!disable_subsongs && (pos & XMPIN_POS_SUBSONG)) { + int new_subsong = LOWORD(pos); + + /* "single subsong mode (don't show info on other subsongs)" */ + if (pos & XMPIN_POS_SUBSONG1) { + // ??? + } + + if (new_subsong && new_subsong != current_subsong) { /* todo implicit? */ + if (current_file) + return -1; + + vgmstream = init_vgmstream_xmplay(current_file, current_fn, current_subsong+1); + if (!vgmstream) return -1; + + current_subsong = new_subsong; + return 0.0; + } + } +#endif + + seek_vgmstream(vgmstream, seek_sample); + + decode_pos_samples = seek_sample; + + cpos = (double)decode_pos_samples / vgmstream->sample_rate; + return cpos; +} + +/* decode some sample data */ +DWORD WINAPI xmplay_Process(float* buf, DWORD bufsize) { + int32_t i, done, samples_to_do; + BOOL do_loop = xmpfin->GetLooping(); + float *sbuf = buf; + + + bufsize /= output_channels; + + samples_to_do = do_loop ? bufsize : length_samples - decode_pos_samples; + if (samples_to_do > bufsize) + samples_to_do = bufsize; + + /* decode */ + done = 0; + while (done < samples_to_do) { + int to_do = SAMPLE_BUFFER_SIZE; + if (to_do > samples_to_do - done) + to_do = samples_to_do - done; + + render_vgmstream(sample_buffer, to_do, vgmstream); + + for (i = 0; i < to_do * output_channels; i++) { + *sbuf++ = sample_buffer[i] * 1.0f / 32768.0f; + } + + done += to_do; + } + + sbuf = buf; + + decode_pos_samples += done; + + return done * output_channels; +} + +static DWORD WINAPI xmplay_GetSubSongs(float *length) { + int subsong_count; + + if (!vgmstream) + return 0; + + subsong_count = vgmstream->num_streams; + if (disable_subsongs || subsong_count == 0) + subsong_count = 1; + + /* get times for all subsongs */ + //todo request updating playlist update every subsong change instead? + { + int stream_length_samples; + + /* not good for vgmstream as would mean re-parsing many times */ + //int i; + //for (i = 0; i < subsong_count; i++) { + // float subsong_length = ... + // *length += subsong_length; + //} + + /* simply use the current length */ //todo just use 0? + length_samples = vgmstream_get_samples(vgmstream); + *length = (float)length_samples / (float)vgmstream->sample_rate; + } + + return subsong_count; +} + +/* *********************************** */ + +/* main plugin def, see xmpin.h */ +XMPIN vgmstream_xmpin = { + XMPIN_FLAG_CANSTREAM, + "vgmstream for XMPlay", + working_extension_list, + xmplay_About, + NULL,//XMP_Config + xmplay_CheckFile, + xmplay_GetFileInfo, + xmplay_Open, + xmplay_Close, + NULL, + xmplay_SetFormat, + xmplay_GetTags, //(OPTIONAL) --actually mandatory + xmplay_GetInfoText, + xmplay_GetGeneralInfo, + NULL,//GetMessage - text for the "Message" tab window/tab (OPTIONAL) + xmplay_SetPosition, + xmplay_GetGranularity, + NULL, + xmplay_Process, + NULL, + NULL, + xmplay_GetSubSongs, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +/* get the plugin's XMPIN interface */ +__declspec(dllexport) XMPIN* WINAPI XMPIN_GetInterface(UINT32 face, InterfaceProc faceproc) { + if (face != XMPIN_FACE) { + // unsupported version + if (face < XMPIN_FACE && !shownerror) { + MessageBox(0, + "The xmp-vgmstream plugin requires XMPlay 3.8 or above.\n\n" + "Please update at:\n" + "http://www.un4seen.com/xmplay.html\n" + "http://www.un4seen.com/stuff/xmplay.exe", 0, MB_ICONEXCLAMATION); + shownerror = 1; + } + return NULL; + } + + xmpfin = (XMPFUNC_IN*)faceproc(XMPFUNC_IN_FACE); + xmpfmisc = (XMPFUNC_MISC*)faceproc(XMPFUNC_MISC_FACE); + xmpffile = (XMPFUNC_FILE*)faceproc(XMPFUNC_FILE_FACE); + + build_extension_list(); + + return &vgmstream_xmpin; +} + +#if 0 +// needed? +BOOL WINAPI DllMain(HINSTANCE hDLL, DWORD reason, LPVOID reserved) { + switch (reason) { + case DLL_PROCESS_ATTACH: + DisableThreadLibraryCalls(hDLL); + break; + } + return TRUE; +} +#endif From a36edd592bf7a3f264535f67228480a23ea2017a Mon Sep 17 00:00:00 2001 From: bnnm Date: Thu, 12 Aug 2021 20:01:56 +0200 Subject: [PATCH 09/11] build: update chmod +x for helper .sh --- make-build.sh | 0 version-get.sh | 0 version-make.sh | 0 3 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 make-build.sh mode change 100644 => 100755 version-get.sh mode change 100644 => 100755 version-make.sh diff --git a/make-build.sh b/make-build.sh old mode 100644 new mode 100755 diff --git a/version-get.sh b/version-get.sh old mode 100644 new mode 100755 diff --git a/version-make.sh b/version-make.sh old mode 100644 new mode 100755 From 9407cda1579e5746ca18a579752162d933f02813 Mon Sep 17 00:00:00 2001 From: bnnm Date: Thu, 12 Aug 2021 20:02:32 +0200 Subject: [PATCH 10/11] cmake: tweak to avoid permission failure on linux --- CMakeLists.txt | 10 +++++++--- doc/BUILD.md | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 47262bdc..a41d0988 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -85,12 +85,16 @@ endif() # Set autogenerated version if(MSVC) set(VGM_VERSION_GENERATOR version-make.bat) + add_custom_command(OUTPUT ${VGM_SOURCE_DIR}/version_auto.h + COMMAND "${VGM_SOURCE_DIR}/${VGM_VERSION_GENERATOR}" + DEPENDS ${VGM_SOURCE_DIR}/${VGM_VERSION_GENERATOR}) else() + # linux uses 'sh' so git-less (src zip) builds can run without chmod -x (script) set(VGM_VERSION_GENERATOR version-make.sh) + add_custom_command(OUTPUT ${VGM_SOURCE_DIR}/version_auto.h + COMMAND sh "${VGM_SOURCE_DIR}/${VGM_VERSION_GENERATOR}" + DEPENDS ${VGM_SOURCE_DIR}/${VGM_VERSION_GENERATOR}) endif() -add_custom_command(OUTPUT ${VGM_SOURCE_DIR}/version_auto.h - COMMAND "${VGM_SOURCE_DIR}/${VGM_VERSION_GENERATOR}" - DEPENDS ${VGM_SOURCE_DIR}/${VGM_VERSION_GENERATOR}) add_custom_target(version_h ALL DEPENDS ${VGM_SOURCE_DIR}/version_auto.h) # FFmpeg detection diff --git a/doc/BUILD.md b/doc/BUILD.md index db91ad67..8fc8c301 100644 --- a/doc/BUILD.md +++ b/doc/BUILD.md @@ -80,6 +80,7 @@ sudo apt-get install -y git git clone https://github.com/vgmstream/vgmstream cd vgmstream +# in case they weren't set chmod +x version-get.sh version-make.sh make-build.sh # warning: installs stuff, check all "apt install" @@ -92,7 +93,7 @@ Tool used to generate common build files (for *make*, *VS/MSBuild*, etc), that i If you wish to use CMake see [CMAKE.md](CMAKE.md). Some extra info is only mentioned in this doc though. -Note that doing in-source builds of CMake (`cmake .` / selecting `./vgmstream` as output dir) is not recommended and may clobber default build files. +Note that doing in-source builds of CMake (`cmake .` / selecting `./vgmstream` as output dir) is not recommended and may clobber default build files (try `cmake -S . -B build` / using some `./build` subfolder). ### autotools (builds) Autogenerated *make* scripts, used by some modules (mainly Audacious for Linux, and external libs). From a008645c0f5165b52358f63832c173e224db521f Mon Sep 17 00:00:00 2001 From: bnnm Date: Thu, 12 Aug 2021 20:03:14 +0200 Subject: [PATCH 11/11] build: fix building with ffmpeg + without mpeg --- src/coding/mpeg_custom_utils.c | 4 ++-- src/coding/mpeg_decoder.h | 41 +++++++++++++++++----------------- src/meta/ffmpeg.c | 2 -- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/coding/mpeg_custom_utils.c b/src/coding/mpeg_custom_utils.c index 451b1d1c..26d10396 100644 --- a/src/coding/mpeg_custom_utils.c +++ b/src/coding/mpeg_custom_utils.c @@ -232,7 +232,9 @@ int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL* stream, mpeg_codec_data* d fail: return 0; } +#endif +//TODO: move to a better place /*****************/ /* FRAME HELPERS */ @@ -475,5 +477,3 @@ fail: VGM_LOG("MPEG: sample reader failed at %lx\n", offset); return 0; } - -#endif diff --git a/src/coding/mpeg_decoder.h b/src/coding/mpeg_decoder.h index 824fe53f..724ee199 100644 --- a/src/coding/mpeg_decoder.h +++ b/src/coding/mpeg_decoder.h @@ -1,21 +1,12 @@ #ifndef _MPEG_DECODER_H_ #define _MPEG_DECODER_H_ -#include #include "../vgmstream.h" #include "../coding/coding.h" /* used by mpeg_decoder.c, but scattered in other .c files */ #ifdef VGM_USE_MPEG -typedef struct { - int version; - int layer; - int bit_rate; - int sample_rate; - int frame_samples; - int frame_size; /* bytes */ - int channels; -} mpeg_frame_info; +#include /* represents a single MPEG stream */ typedef struct { @@ -70,18 +61,28 @@ struct mpeg_codec_data { }; -int mpeg_get_frame_info(STREAMFILE *streamfile, off_t offset, mpeg_frame_info * info); +typedef struct { + int version; + int layer; + int bit_rate; + int sample_rate; + int frame_samples; + int frame_size; /* bytes */ + int channels; +} mpeg_frame_info; -int mpeg_custom_setup_init_default(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type); -int mpeg_custom_setup_init_ealayer3(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type); -int mpeg_custom_setup_init_awc(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type); -int mpeg_custom_setup_init_eamp3(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type); +int mpeg_get_frame_info(STREAMFILE* sf, off_t offset, mpeg_frame_info* info); -int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream); -int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream); -int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream); -int mpeg_custom_parse_frame_awc(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream); -int mpeg_custom_parse_frame_eamp3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream); +int mpeg_custom_setup_init_default(STREAMFILE* sf, off_t start_offset, mpeg_codec_data* data, coding_t* coding_type); +int mpeg_custom_setup_init_ealayer3(STREAMFILE* sf, off_t start_offset, mpeg_codec_data* data, coding_t* coding_type); +int mpeg_custom_setup_init_awc(STREAMFILE* sf, off_t start_offset, mpeg_codec_data* data, coding_t* coding_type); +int mpeg_custom_setup_init_eamp3(STREAMFILE* sf, off_t start_offset, mpeg_codec_data* data, coding_t* coding_type); + +int mpeg_custom_parse_frame_default(VGMSTREAMCHANNEL* stream, mpeg_codec_data* data, int num_stream); +int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL* stream, mpeg_codec_data* data, int num_stream); +int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL* stream, mpeg_codec_data* data, int num_stream); +int mpeg_custom_parse_frame_awc(VGMSTREAMCHANNEL* stream, mpeg_codec_data* data, int num_stream); +int mpeg_custom_parse_frame_eamp3(VGMSTREAMCHANNEL* stream, mpeg_codec_data* data, int num_stream); #endif/* VGM_USE_MPEG */ diff --git a/src/meta/ffmpeg.c b/src/meta/ffmpeg.c index 606df921..748d1ae3 100644 --- a/src/meta/ffmpeg.c +++ b/src/meta/ffmpeg.c @@ -80,7 +80,6 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) { } } -#ifdef VGM_USE_MPEG /* hack for MP3 files (will return 0 samples if not an actual file) * .mus: Marc Ecko's Getting Up (PC) */ if (!num_samples && check_extensions(sf, "mp3,lmp3,mus")) { @@ -89,7 +88,6 @@ VGMSTREAM* init_vgmstream_ffmpeg(STREAMFILE* sf) { /* this seems correct thankfully */ //ffmpeg_set_skip_samples(data, encoder_delay); } -#endif /* hack for MPC */ if (is_id32be(0x00, sf, "MP+\x07") || /* Musepack V7 */