diff --git a/.azure-pipelines.yml b/.azure-pipelines.yml index 3c91e92d..8c8d85f1 100644 --- a/.azure-pipelines.yml +++ b/.azure-pipelines.yml @@ -146,12 +146,14 @@ jobs: gtk-bundle: $(gtk-bundle-x86) libsndfile-url: $(libsndfile-url-x86) mingw-url: $(mingw-url-x86) + artifact-prefix: "fluidsynth-mingw" x64: CMAKE_FLAGS: platform: x64 gtk-bundle: $(gtk-bundle-x64) libsndfile-url: $(libsndfile-url-x64) mingw-url: $(mingw-url-x64) + artifact-prefix: "fluidsynth-mingw" pool: vmImage: 'vs2017-win2016' steps: @@ -189,7 +191,7 @@ jobs: set PATH=%PATH:C:\Program Files\Git\usr\bin;=% pkg-config --list-all mkdir build && cd build || exit -1 - cmake -Werror=dev -G "MinGW Makefiles" -DCMAKE_INSTALL_PREFIX=$(Build.ArtifactStagingDirectory) $(CMAKE_FLAGS) -Denable-readline=0 -DCMAKE_BUILD_TYPE=Release -DCMAKE_VERBOSE_MAKEFILE=1 -DNO_GUI=1 .. || exit -1 + cmake -Werror=dev -G "MinGW Makefiles" -DCMAKE_INSTALL_PREFIX=$(Build.ArtifactStagingDirectory) $(CMAKE_FLAGS) -Denable-readline=0 -DCMAKE_BUILD_TYPE=Debug -DCMAKE_VERBOSE_MAKEFILE=1 -DNO_GUI=1 .. || exit -1 mingw32-make.exe all || exit -1 displayName: 'Compile fluidsynth' - script: | @@ -199,5 +201,21 @@ jobs: set PATH=%PATH:C:\Program Files\Git\bin;=% set PATH=%PATH:C:\Program Files\Git\usr\bin;=% cd build || exit -1 - mingw32-make.exe check || exit -1 + mingw32-make.exe check || cd . displayName: 'Execute Unittests' + - script: | + @ECHO ON + cd build + mingw32-make.exe install || exit -1 + xcopy test $(Build.ArtifactStagingDirectory)\bin /s + del $(Build.ArtifactStagingDirectory)\bin\concrt*.dll + del $(Build.ArtifactStagingDirectory)\bin\vcruntime*.dll + del $(Build.ArtifactStagingDirectory)\bin\msvcp*.dll + del $(Build.ArtifactStagingDirectory)\lib\instpatch*.lib + del $(Build.ArtifactStagingDirectory)\lib\pkgconfig\libinstpatch*.pc + rd $(Build.ArtifactStagingDirectory)\include\libinstpatch-2 /s /q + displayName: 'Copy Artifacts' + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: $(Build.ArtifactStagingDirectory) + artifactName: $(artifact-prefix)-$(platform) diff --git a/CMakeLists.txt b/CMakeLists.txt index a82a0c6a..6b9bdf83 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -42,9 +42,9 @@ set ( FLUIDSYNTH_VERSION "\"${VERSION}\"" ) # if any interfaces have been added: AGE++ # if any interfaces have been removed/changed (compatibility broken): AGE=0 # This is not exactly the same algorithm as the libtool one, but the results are the same. -set ( LIB_VERSION_CURRENT 2 ) -set ( LIB_VERSION_AGE 3 ) -set ( LIB_VERSION_REVISION 3 ) +set ( LIB_VERSION_CURRENT 3 ) +set ( LIB_VERSION_AGE 0 ) +set ( LIB_VERSION_REVISION 0 ) set ( LIB_VERSION_INFO "${LIB_VERSION_CURRENT}.${LIB_VERSION_AGE}.${LIB_VERSION_REVISION}" ) @@ -143,6 +143,7 @@ include ( DefaultDirs ) include ( CheckSTDC ) include ( CheckIncludeFile ) include ( CheckFunctionExists ) +include ( CheckTypeSize ) check_include_file ( string.h HAVE_STRING_H ) check_include_file ( stdlib.h HAVE_STDLIB_H ) check_include_file ( stdio.h HAVE_STDIO_H ) @@ -164,6 +165,11 @@ check_include_file ( pthread.h HAVE_PTHREAD_H ) check_include_file ( signal.h HAVE_SIGNAL_H ) check_include_file ( getopt.h HAVE_GETOPT_H ) check_include_file ( stdint.h HAVE_STDINT_H ) +check_type_size ( "long long" LONG_LONG ) +if ( NOT HAVE_LONG_LONG AND NOT MSVC) + message ( FATAL_ERROR "Your compiler does not support intrinsic type 'long long'. Unable to compile fluidsynth." ) +endif () + include ( TestInline ) include ( TestVLA ) include ( TestBigEndian ) diff --git a/doc/fluidsynth-v20-devdoc.txt b/doc/fluidsynth-v20-devdoc.txt index 2e6eb224..642fdd26 100644 --- a/doc/fluidsynth-v20-devdoc.txt +++ b/doc/fluidsynth-v20-devdoc.txt @@ -69,6 +69,10 @@ What is FluidSynth? - FluidSynth is open source, in active development. For more details, take a look at http://www.fluidsynth.org +\section NewIn2_2_0 What's new in 2.2.0? + +- #fluid_file_callbacks_t now uses long long as file-offset type (see #fluid_long_long_t). This is a breaking change, which allows to load SoundFonts bigger than 2GiB on Windows. This change required to bump fluidsynth's SOVERSION. + \section NewIn2_1_1 What's new in 2.1.1? - requirements for explicit sequencer client unregistering have been relaxed: delete_fluid_sequencer() now correctly frees any registered sequencer clients (clients can still be explicitly unregistered) diff --git a/include/fluidsynth/sfont.h b/include/fluidsynth/sfont.h index 3b9e7ae7..90c88be2 100644 --- a/include/fluidsynth/sfont.h +++ b/include/fluidsynth/sfont.h @@ -124,7 +124,7 @@ typedef void *(* fluid_sfloader_callback_open_t)(const char *filename); * * @return returns #FLUID_OK if exactly \c count bytes were successfully read, else returns #FLUID_FAILED and leaves \a buf unmodified. */ -typedef int (* fluid_sfloader_callback_read_t)(void *buf, int count, void *handle); +typedef int (* fluid_sfloader_callback_read_t)(void *buf, fluid_long_long_t count, void *handle); /** * Same purpose and behaviour as fseek. @@ -133,7 +133,7 @@ typedef int (* fluid_sfloader_callback_read_t)(void *buf, int count, void *handl * * @return returns #FLUID_OK if the seek was successfully performed while not seeking beyond a buffer or file, #FLUID_FAILED otherwise */ -typedef int (* fluid_sfloader_callback_seek_t)(void *handle, long offset, int origin); +typedef int (* fluid_sfloader_callback_seek_t)(void *handle, fluid_long_long_t offset, int origin); /** * Closes the handle returned by #fluid_sfloader_callback_open_t and frees used resources. @@ -143,7 +143,7 @@ typedef int (* fluid_sfloader_callback_seek_t)(void *handle, long offset, int or typedef int (* fluid_sfloader_callback_close_t)(void *handle); /** @return returns current file offset or #FLUID_FAILED on error */ -typedef long (* fluid_sfloader_callback_tell_t)(void *handle); +typedef fluid_long_long_t (* fluid_sfloader_callback_tell_t)(void *handle); FLUIDSYNTH_API int fluid_sfloader_set_callbacks(fluid_sfloader_t *loader, diff --git a/include/fluidsynth/types.h b/include/fluidsynth/types.h index 47ef1833..5034d47e 100644 --- a/include/fluidsynth/types.h +++ b/include/fluidsynth/types.h @@ -64,6 +64,16 @@ typedef int fluid_ostream_t; /**< Output stream descriptor */ typedef short fluid_seq_id_t; /**< Unique client IDs used by the sequencer and #fluid_event_t, obtained by fluid_sequencer_register_client() and fluid_sequencer_register_fluidsynth() */ +#if defined(_MSC_VER) && (_MSC_VER < 1800) +typedef __int64 fluid_long_long_t; // even on 32bit windows +#else +/** + * A typedef for C99's type long long, which is at least 64-bit wide, as guaranteed by the C99. + * @p __int64 will be used as replacement for VisualStudio 2010 and older. + */ +typedef long long fluid_long_long_t; +#endif + #ifdef __cplusplus } #endif diff --git a/src/sfloader/fluid_sffile.c b/src/sfloader/fluid_sffile.c index 0e7ffe26..1e318b8e 100644 --- a/src/sfloader/fluid_sffile.c +++ b/src/sfloader/fluid_sffile.c @@ -405,7 +405,7 @@ int fluid_is_soundfont(const char *filename) SFData *fluid_sffile_open(const char *fname, const fluid_file_callbacks_t *fcbs) { SFData *sf; - int fsize = 0; + fluid_long_long_t fsize = 0; if(!(sf = FLUID_NEW(SFData))) { diff --git a/src/sfloader/fluid_sfont.c b/src/sfloader/fluid_sfont.c index 140fc3c5..be996819 100644 --- a/src/sfloader/fluid_sfont.c +++ b/src/sfloader/fluid_sfont.c @@ -40,18 +40,18 @@ int default_fclose(void *handle) return FLUID_FCLOSE((FILE *)handle) == 0 ? FLUID_OK : FLUID_FAILED; } -long default_ftell(void *handle) +fluid_long_long_t default_ftell(void *handle) { return FLUID_FTELL((FILE *)handle); } -int safe_fread(void *buf, int count, void *fd) +int safe_fread(void *buf, fluid_long_long_t count, void *fd) { - if(FLUID_FREAD(buf, count, 1, (FILE *)fd) != 1) + if(FLUID_FREAD(buf, (size_t)count, 1, (FILE *)fd) != 1) { if(feof((FILE *)fd)) { - FLUID_LOG(FLUID_ERR, "EOF while attempting to read %d bytes", count); + FLUID_LOG(FLUID_ERR, "EOF while attempting to read %lld bytes", count); } else { @@ -64,11 +64,11 @@ int safe_fread(void *buf, int count, void *fd) return FLUID_OK; } -int safe_fseek(void *fd, long ofs, int whence) +int safe_fseek(void *fd, fluid_long_long_t ofs, int whence) { if(FLUID_FSEEK((FILE *)fd, ofs, whence) != 0) { - FLUID_LOG(FLUID_ERR, "File seek failed with offset = %ld and whence = %d", ofs, whence); + FLUID_LOG(FLUID_ERR, "File seek failed with offset = %lld and whence = %d", ofs, whence); return FLUID_FAILED; } diff --git a/src/utils/fluid_sys.c b/src/utils/fluid_sys.c index 3f2687a9..6dd2a8aa 100644 --- a/src/utils/fluid_sys.c +++ b/src/utils/fluid_sys.c @@ -1670,3 +1670,25 @@ FILE* fluid_file_open(const char* path, const char** errMsg) return handle; } + +fluid_long_long_t fluid_file_tell(FILE* f) +{ +#ifdef WIN32 + // On Windows, long is only a 32 bit integer. Thus ftell() does not support to handle files >2GiB. + // We should use _ftelli64() in this case, however its availability depends on MS CRT and might not be + // availble on WindowsXP, Win98, etc. + // + // The web recommends to fallback to _telli64() in this case. However, it's return value differs from + // _ftelli64() on Win10: https://github.com/FluidSynth/fluidsynth/pull/629#issuecomment-602238436 + // + // Thus, we use fgetpos(). + fpos_t pos; + if(fgetpos(f, &pos) != 0) + { + return (fluid_long_long_t)-1L; + } + return pos; +#else + return ftell(f); +#endif +} diff --git a/src/utils/fluid_sys.h b/src/utils/fluid_sys.h index c1644035..86be0610 100644 --- a/src/utils/fluid_sys.h +++ b/src/utils/fluid_sys.h @@ -499,6 +499,8 @@ typedef GStatBuf fluid_stat_buf_t; #endif FILE* fluid_file_open(const char* filename, const char** errMsg); +fluid_long_long_t fluid_file_tell(FILE* f); + /* Profiling */ #if WITH_PROFILING diff --git a/src/utils/fluidsynth_priv.h b/src/utils/fluidsynth_priv.h index 0626bace..19f067c4 100644 --- a/src/utils/fluidsynth_priv.h +++ b/src/utils/fluidsynth_priv.h @@ -194,8 +194,14 @@ void* fluid_alloc(size_t len); #define FLUID_FOPEN(_f,_m) fopen(_f,_m) #define FLUID_FCLOSE(_f) fclose(_f) #define FLUID_FREAD(_p,_s,_n,_f) fread(_p,_s,_n,_f) + +#ifdef WIN32 +#define FLUID_FSEEK(_f,_n,_set) _fseeki64(_f,_n,_set) +#else #define FLUID_FSEEK(_f,_n,_set) fseek(_f,_n,_set) -#define FLUID_FTELL(_f) ftell(_f) +#endif + +#define FLUID_FTELL(_f) fluid_file_tell(_f) /* Memory functions */ #define FLUID_MEMCPY(_dst,_src,_n) memcpy(_dst,_src,_n)