Update to fluidsynth-2.2

This commit is contained in:
Robin Gareus 2021-04-18 21:25:20 +02:00
parent dd060b04dc
commit 71788ecfe4
No known key found for this signature in database
GPG key ID: A090BCE02CF57F04
62 changed files with 4719 additions and 2064 deletions

View file

@ -60,6 +60,10 @@ typedef struct
struct _fluid_timer_t
{
long msec;
// Pointer to a function to be executed by the timer.
// This field is set to NULL once the timer is finished to indicate completion.
// This allows for timed waits, rather than waiting forever as fluid_timer_join() does.
fluid_timer_callback_t callback;
void *data;
fluid_thread_t *thread;
@ -85,7 +89,11 @@ static fluid_log_function_t fluid_log_function[LAST_LOG_LEVEL] =
fluid_default_log_function,
fluid_default_log_function,
fluid_default_log_function,
#ifdef DEBUG
fluid_default_log_function
#else
NULL
#endif
};
static void *fluid_log_user_data[LAST_LOG_LEVEL] = { NULL };
@ -149,9 +157,7 @@ fluid_default_log_function(int level, const char *message, void *data)
break;
case FLUID_DBG:
#if DEBUG
FLUID_FPRINTF(out, "%s: debug: %s\n", fluid_libname, message);
#endif
break;
default:
@ -216,9 +222,73 @@ void* fluid_alloc(size_t len)
}
/**
* Convenience wrapper for free() that satisfies at least C90 requirements.
* Especially useful when using fluidsynth with programming languages that do not provide malloc() and free().
* @note Only use this function when the API documentation explicitly says so. Otherwise use adequate \c delete_fluid_* functions.
* Open a file with a UTF-8 string, even in Windows
* @param filename The name of the file to open
* @param mode The mode to open the file in
*/
FILE *fluid_fopen(const char *filename, const char *mode)
{
#if defined(WIN32)
wchar_t *wpath = NULL, *wmode = NULL;
FILE *file = NULL;
int length;
if ((length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename, -1, NULL, 0)) == 0)
{
FLUID_LOG(FLUID_ERR, "Unable to perform MultiByteToWideChar() conversion for filename '%s'. Error was: '%s'", filename, fluid_get_windows_error());
errno = EINVAL;
goto error_recovery;
}
wpath = FLUID_MALLOC(length * sizeof(wchar_t));
if (wpath == NULL)
{
FLUID_LOG(FLUID_PANIC, "Out of memory.");
errno = EINVAL;
goto error_recovery;
}
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, filename, -1, wpath, length);
if ((length = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mode, -1, NULL, 0)) == 0)
{
FLUID_LOG(FLUID_ERR, "Unable to perform MultiByteToWideChar() conversion for mode '%s'. Error was: '%s'", mode, fluid_get_windows_error());
errno = EINVAL;
goto error_recovery;
}
wmode = FLUID_MALLOC(length * sizeof(wchar_t));
if (wmode == NULL)
{
FLUID_LOG(FLUID_PANIC, "Out of memory.");
errno = EINVAL;
goto error_recovery;
}
MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mode, -1, wmode, length);
file = _wfopen(wpath, wmode);
error_recovery:
FLUID_FREE(wpath);
FLUID_FREE(wmode);
return file;
#else
return fopen(filename, mode);
#endif
}
/**
* Wrapper for free() that satisfies at least C90 requirements.
*
* @param ptr Pointer to memory region that should be freed
*
* @note Only use this function when the API documentation explicitly says so. Otherwise use
* adequate \c delete_fluid_* functions.
*
* @warning Calling ::free() on memory that is advised to be freed with fluid_free() results in undefined behaviour!
* (cf.: "Potential Errors Passing CRT Objects Across DLL Boundaries" found in MS Docs)
*
* @since 2.0.7
*/
void fluid_free(void* ptr)
@ -234,7 +304,7 @@ void fluid_free(void* ptr)
* @internal
* @param str Pointer to a string pointer of source to tokenize. Pointer gets
* updated on each invocation to point to beginning of next token. Note that
* token char get's overwritten with a 0 byte. String pointer is set to NULL
* token char gets overwritten with a 0 byte. String pointer is set to NULL
* when final token is returned.
* @param delim String of delimiter chars.
* @return Pointer to the next token or NULL if no more tokens.
@ -441,7 +511,7 @@ fluid_thread_self_set_prio(int prio_level)
* Floating point exceptions
*
* The floating point exception functions were taken from Ircam's
* jMax source code. http://www.ircam.fr/jmax
* jMax source code. https://www.ircam.fr/jmax
*
* FIXME: check in config for i386 machine
*
@ -514,7 +584,7 @@ void fluid_clear_fpe_i386(void)
*/
#if WITH_PROFILING
/* Profiling interface beetween profiling command shell and audio rendering API
/* Profiling interface between profiling command shell and audio rendering API
(FluidProfile_0004.pdf- 3.2.2).
Macros are in defined in fluid_sys.h.
*/
@ -693,8 +763,8 @@ static void fluid_profiling_print_load(double sample_rate, fluid_ostream_t out)
* @param sample_rate the sample rate of audio output.
* @param out output stream device.
*
* When print mode is 1, the function prints all the informations (see below).
* When print mode is 0, the fonction prints only the cpu loads.
* When print mode is 1, the function prints all the information (see below).
* When print mode is 0, the function prints only the cpu loads.
*
* ------------------------------------------------------------------------------
* Duration(microsecond) and cpu loads(%) (sr: 44100 Hz, sp: 22.68 microsecond)
@ -975,7 +1045,7 @@ new_fluid_thread(const char *name, fluid_thread_func_t func, void *data, int pri
#if OLD_GLIB_THREAD_API
/* Make sure g_thread_init has been called.
* FIXME - Probably not a good idea in a shared library,
* Probably not a good idea in a shared library,
* but what can we do *and* remain backwards compatible? */
if(!g_thread_supported())
{
@ -1095,6 +1165,7 @@ fluid_timer_run(void *data)
}
FLUID_LOG(FLUID_DBG, "Timer thread finished");
timer->callback = NULL;
if(timer->auto_destroy)
{
@ -1188,6 +1259,19 @@ fluid_timer_join(fluid_timer_t *timer)
return FLUID_OK;
}
int
fluid_timer_is_running(const fluid_timer_t *timer)
{
// for unit test usage only
return timer->callback != NULL;
}
long fluid_timer_get_interval(const fluid_timer_t * timer)
{
// for unit test usage only
return timer->msec;
}
/***************************************************************
*
@ -1199,7 +1283,7 @@ fluid_timer_join(fluid_timer_t *timer)
* Get standard in stream handle.
* @return Standard in stream.
*/
fluid_istream_t
static fluid_istream_t
fluid_get_stdin(void)
{
return STDIN_FILENO;
@ -1209,7 +1293,7 @@ fluid_get_stdin(void)
* Get standard output stream handle.
* @return Standard out stream.
*/
fluid_ostream_t
static fluid_ostream_t
fluid_get_stdout(void)
{
return STDOUT_FILENO;
@ -1669,3 +1753,50 @@ 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
}
#ifdef WIN32
// not thread-safe!
char* fluid_get_windows_error(void)
{
static TCHAR err[1024];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError(),
MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
err,
sizeof(err)/sizeof(err[0]),
NULL);
#ifdef _UNICODE
static char ascii_err[sizeof(err)];
WideCharToMultiByte(CP_UTF8, 0, err, -1, ascii_err, sizeof(ascii_err)/sizeof(ascii_err[0]), 0, 0);
return ascii_err;
#else
return err;
#endif
}
#endif