mirror of
https://github.com/reactos/reactos.git
synced 2025-07-16 05:04:02 +00:00
[LIBMPG123]
- Update to version 1.25.0 CORE-13451 svn path=/trunk/; revision=75093
This commit is contained in:
parent
f5be5e8bfe
commit
d1d15ad1a6
14 changed files with 949 additions and 278 deletions
|
@ -16,5 +16,5 @@ add_library(winemp3.acm SHARED
|
|||
set_module_type(winemp3.acm win32dll)
|
||||
set_target_properties(winemp3.acm PROPERTIES SUFFIX "")
|
||||
target_link_libraries(winemp3.acm wine libmpg123 oldnames)
|
||||
add_importlibs(winemp3.acm winmm user32 msvcrt kernel32 ntdll)
|
||||
add_importlibs(winemp3.acm shlwapi winmm user32 msvcrt kernel32 ntdll)
|
||||
add_cd_file(TARGET winemp3.acm DESTINATION reactos/system32 FOR all)
|
||||
|
|
|
@ -15,10 +15,14 @@
|
|||
#define MPG123_COMPAT_H
|
||||
|
||||
#include "config.h"
|
||||
#include "intsym.h"
|
||||
|
||||
/* Needed for strdup(), in strict mode ... */
|
||||
#ifndef _XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE 500
|
||||
/* For --nagging compilation with -std=c89, we need
|
||||
to disable the inline keyword. */
|
||||
#ifdef PLAIN_C89
|
||||
#ifndef inline
|
||||
#define inline
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
@ -98,8 +102,10 @@
|
|||
typedef unsigned char byte;
|
||||
|
||||
#ifndef __REACTOS__
|
||||
#ifdef _MSC_VER
|
||||
typedef long ssize_t;
|
||||
#if defined(_MSC_VER) && !defined(MPG123_DEF_SSIZE_T)
|
||||
#define MPG123_DEF_SSIZE_T
|
||||
#include <stddef.h>
|
||||
typedef ptrdiff_t ssize_t;
|
||||
#endif
|
||||
#endif /* __REACTOS__ */
|
||||
|
||||
|
@ -109,9 +115,9 @@ void *safe_realloc(void *ptr, size_t size);
|
|||
const char *strerror(int errnum);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
char *strdup(const char *s);
|
||||
#endif
|
||||
/* Roll our own strdup() that does not depend on libc feature test macros
|
||||
and returns NULL on NULL input instead of crashing. */
|
||||
char* compat_strdup(const char *s);
|
||||
|
||||
/* If we have the size checks enabled, try to derive some sane printfs.
|
||||
Simple start: Use max integer type and format if long is not big enough.
|
||||
|
@ -140,6 +146,10 @@ typedef intmax_t ssize_p;
|
|||
typedef long ssize_p;
|
||||
#endif
|
||||
|
||||
/* Get an environment variable, possibly converted to UTF-8 from wide string.
|
||||
The return value is a copy that you shall free. */
|
||||
char *compat_getenv(const char* name);
|
||||
|
||||
/**
|
||||
* Opening a file handle can be different.
|
||||
* This function here is defined to take a path in native encoding (ISO8859 / UTF-8 / ...), or, when MS Windows Unicode support is enabled, an UTF-8 string that will be converted back to native UCS-2 (wide character) before calling the system's open function.
|
||||
|
@ -149,6 +159,10 @@ typedef long ssize_p;
|
|||
*/
|
||||
int compat_open(const char *filename, int flags);
|
||||
FILE* compat_fopen(const char *filename, const char *mode);
|
||||
/**
|
||||
* Also fdopen to avoid having to define POSIX macros in various source files.
|
||||
*/
|
||||
FILE* compat_fdopen(int fd, const char *mode);
|
||||
|
||||
/**
|
||||
* Closing a file handle can be platform specific.
|
||||
|
@ -190,6 +204,67 @@ int win32_wide_utf8(const wchar_t * const wptr, char **mbptr, size_t * buflen);
|
|||
int win32_utf8_wide(const char *const mbptr, wchar_t **wptr, size_t *buflen);
|
||||
#endif
|
||||
|
||||
/*
|
||||
A little bit of path abstraction: We always work with plain char strings
|
||||
that usually represent POSIX-ish UTF-8 paths (something like c:/some/file
|
||||
might appear). For Windows, those are converted to wide strings with \
|
||||
instead of / and possible fun is had with prefixes to get around the old
|
||||
path length limit. Outside of the compat library, that stuff should not
|
||||
matter, although something like //?/UNC/server/some/file could be thrown
|
||||
around as UTF-8 string, to be converted to a wide \\?\UNC\server\some\file
|
||||
just before handing it to Windows API.
|
||||
|
||||
There is a lot of unnecessary memory allocation and string copying because
|
||||
of this, but this filesystem stuff is not really relevant to mpg123
|
||||
performance, so the goal is to keep the code outside the compatibility layer
|
||||
simple.
|
||||
*/
|
||||
|
||||
/*
|
||||
Concatenate a prefix and a path, one of them alowed to be NULL.
|
||||
If the path is already absolute, the prefix is ignored. Relative
|
||||
parts (like /..) are resolved if this is sensible for the platform
|
||||
(meaning: for Windows), else they are preserved (on POSIX, actual
|
||||
file system access would be needed because of symlinks).
|
||||
*/
|
||||
char* compat_catpath(const char *prefix, const char* path);
|
||||
|
||||
/* Return 1 if the given path indicates an existing directory,
|
||||
0 otherwise. */
|
||||
int compat_isdir(const char *path);
|
||||
|
||||
/*
|
||||
Directory traversal. This talks ASCII/UTF-8 paths externally, converts
|
||||
to/from wchar_t internally if the platform wants that. Returning NULL
|
||||
means failure to open/end of listing.
|
||||
There is no promise about sorting entries.
|
||||
*/
|
||||
struct compat_dir;
|
||||
/* Returns NULL if either directory failed to open or listing is empty.
|
||||
Listing can still be empty even if non-NULL, so always rely on the
|
||||
nextfile/nextdir functions. */
|
||||
struct compat_dir* compat_diropen(char *path);
|
||||
void compat_dirclose(struct compat_dir*);
|
||||
/* Get the next entry that is a file (or symlink to one).
|
||||
The returned string is a copy that needs to be freed after use. */
|
||||
char* compat_nextfile(struct compat_dir*);
|
||||
/* Get the next entry that is a directory (or symlink to one).
|
||||
The returned string is a copy that needs to be freed after use. */
|
||||
char* compat_nextdir (struct compat_dir*);
|
||||
|
||||
#ifdef USE_MODULES
|
||||
/*
|
||||
For keeping the path mess local, a system-specific dlopen() variant
|
||||
is contained in here, too. This is very thin wrapping, even sparing
|
||||
definition of a handle type, just using void pointers.
|
||||
Use of absolute paths is a good idea if you want to be sure which
|
||||
file is openend, as default search paths vary.
|
||||
*/
|
||||
void *compat_dlopen (const char *path);
|
||||
void *compat_dlsym (void *handle, const char* name);
|
||||
void compat_dlclose(void *handle);
|
||||
#endif
|
||||
|
||||
/* Blocking write/read of data with signal resilience.
|
||||
Both continue after being interrupted by signals and always return the
|
||||
amount of processed data (shortage indicating actual problem or EOF). */
|
||||
|
|
|
@ -13,6 +13,13 @@
|
|||
#include "config.h"
|
||||
#include "intsym.h"
|
||||
|
||||
#if (defined OPT_I486) || (defined OPT_I586) || (defined OPT_I586_DITHER) \
|
||||
|| (defined OPT_MMX) || (defined OPT_SSE) || (defined OPT_3DNOW) || (defined OPT_3DNOWEXT) \
|
||||
|| (defined OPT_3DNOW_VINTAGE) || (defined OPT_3DNOWEXT_VINTAGE) \
|
||||
|| (defined OPT_SSE_VINTAGE)
|
||||
#define OPT_X86
|
||||
#endif
|
||||
|
||||
#ifdef CCALIGN
|
||||
#define MOVUAPS movaps
|
||||
#else
|
||||
|
@ -49,9 +56,17 @@
|
|||
#define ALIGN32 .align 32
|
||||
#define ALIGN64 .align 64
|
||||
#else
|
||||
#ifdef ASMALIGN_ARMASM
|
||||
#define ALIGN4 ALIGN 4
|
||||
#define ALIGN8 ALIGN 8
|
||||
#define ALIGN16 ALIGN 16
|
||||
#define ALIGN32 ALIGN 32
|
||||
#define ALIGN64 ALIGN 64
|
||||
#else
|
||||
#error "Dunno how assembler alignment works. Please specify."
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -61,7 +76,7 @@
|
|||
#if defined(__USER_LABEL_PREFIX__)
|
||||
#define ASM_NAME(a) MANGLE_MACROCAT(__USER_LABEL_PREFIX__,a)
|
||||
#define ASM_VALUE(a) MANGLE_MACROCAT($,ASM_NAME(a))
|
||||
#elif defined(__CYGWIN__) || defined(_WIN32) && !defined (_WIN64) || defined(__OS2__) || \
|
||||
#elif defined(__CYGWIN__) || defined(_WIN32) && !defined (_WIN64) && !defined (_M_ARM) || defined(__OS2__) || \
|
||||
(defined(__OpenBSD__) && !defined(__ELF__)) || defined(__APPLE__)
|
||||
#define ASM_NAME(a) MANGLE_MACROCAT(_,a)
|
||||
#define ASM_VALUE(a) MANGLE_MACROCAT($_,a)
|
||||
|
@ -70,6 +85,62 @@
|
|||
#define ASM_VALUE(a) MANGLE_MACROCAT($,a)
|
||||
#endif
|
||||
|
||||
/* Enable position-independent code for certain platforms. */
|
||||
|
||||
#if defined(OPT_X86)
|
||||
|
||||
#define _EBX_ %ebx
|
||||
|
||||
#if defined(PIC) && defined(__ELF__)
|
||||
|
||||
/* ELF binaries (Unix/Linux) */
|
||||
#define LOCAL_VAR(a) a ## @GOTOFF(_EBX_)
|
||||
#define GLOBAL_VAR(a) ASM_NAME(a) ## @GOTOFF(_EBX_)
|
||||
#define GLOBAL_VAR_PTR(a) ASM_NAME(a) ## @GOT(_EBX_)
|
||||
#define FUNC(a) ASM_NAME(a)
|
||||
#define EXTERNAL_FUNC(a) ASM_NAME(a) ## @PLT
|
||||
#undef ASM_VALUE
|
||||
#define ASM_VALUE(a) MANGLE_MACROCAT($,a) ##@GOTOFF
|
||||
#define GET_GOT \
|
||||
call 1f; \
|
||||
1: \
|
||||
pop _EBX_; \
|
||||
2: \
|
||||
addl $_GLOBAL_OFFSET_TABLE_ + (2b-1b), _EBX_
|
||||
#define PREPARE_GOT pushl _EBX_
|
||||
#define RESTORE_GOT popl _EBX_
|
||||
|
||||
#elif defined(PIC) && defined(__APPLE__)
|
||||
|
||||
/* Mach-O binaries (OSX/iOS) */
|
||||
#define LOCAL_VAR(a) a ## - Lpic_base(_EBX_)
|
||||
#define GLOBAL_VAR(a) #error This ABI cannot access non-local symbols directly.
|
||||
#define GLOBAL_VAR_PTR(a) L_ ## a ## - Lpic_base(_EBX_)
|
||||
#define FUNC(a) L_ ## a
|
||||
#define EXTERNAL_FUNC(a) L_ ## a
|
||||
#define GET_GOT \
|
||||
call Lpic_base; \
|
||||
Lpic_base: \
|
||||
pop _EBX_
|
||||
#define PREPARE_GOT pushl _EBX_
|
||||
#define RESTORE_GOT popl _EBX_
|
||||
|
||||
#else
|
||||
|
||||
/* Dummies for everyone else. */
|
||||
#define LOCAL_VAR(a) a
|
||||
#define GLOBAL_VAR ASM_NAME
|
||||
#define GLOBAL_VAR_PTR(a) #error Cannot use indirect addressing in non-PIC object.
|
||||
#define FUNC ASM_NAME
|
||||
#define EXTERNAL_FUNC ASM_NAME
|
||||
#define GET_GOT
|
||||
#define PREPARE_GOT
|
||||
#define RESTORE_GOT
|
||||
|
||||
#endif /* PIC variants */
|
||||
|
||||
#endif /* OPT_X86 */
|
||||
|
||||
#if defined(__CYGWIN__) || defined(__MINGW32__) || defined(__APPLE__)
|
||||
#define COMM(a,b,c) .comm a,b
|
||||
#else
|
||||
|
@ -82,6 +153,13 @@
|
|||
#define BSS .bss
|
||||
#endif
|
||||
|
||||
/* armasm for WIN32 UWP */
|
||||
#ifdef _M_ARM
|
||||
#define GLOBAL_SYMBOL EXPORT
|
||||
#else
|
||||
#define GLOBAL_SYMBOL .globl
|
||||
#endif
|
||||
|
||||
/* Mark non-executable stack.
|
||||
It's mainly for GNU on Linux... who else does (not) like this? */
|
||||
#if !defined(__SUNPRO_C) && defined(__linux__) && defined(__ELF__)
|
||||
|
@ -94,7 +172,7 @@
|
|||
#define NONEXEC_STACK
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__) && (defined(_WIN64) || defined (__CYGWIN__))
|
||||
#if (defined(__x86_64__) || defined(_M_X64)) && (defined(_WIN64) || defined (__CYGWIN__))
|
||||
#define IS_MSABI 1 /* Not using SYSV */
|
||||
#endif
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ static inline int16_t idiv_signed_rounded(int32_t x, int shift)
|
|||
/* From now on for single precision float... double precision is a possible option once we added some bits. But, it would be rather insane. */
|
||||
#ifndef REAL_TO_SHORT
|
||||
|
||||
#if (defined FORCE_ACCURATE) || (defined ACCURATE_ROUNDING)
|
||||
/* Define the accurate rounding function. */
|
||||
# if (defined REAL_IS_FLOAT) && (defined IEEE_FLOAT)
|
||||
/* This function is only available for IEEE754 single-precision values
|
||||
|
@ -51,6 +52,7 @@ static inline int16_t ftoi16(float x)
|
|||
/* The "proper" rounding, plain C, a bit slow. */
|
||||
# define REAL_TO_SHORT_ACCURATE(x) (short)((x)>0.0?(x)+0.5:(x)-0.5)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Now define the normal rounding. */
|
||||
# ifdef ACCURATE_ROUNDING
|
||||
|
|
|
@ -15,11 +15,12 @@
|
|||
That's not memory efficient since there's doubled code, but it's easier than giving another function pointer.
|
||||
Maybe I'll change it in future, but now I need something that works.
|
||||
|
||||
Original comment from MPlayer source follows:
|
||||
Original comment from MPlayer source follows. Regarding the license history see
|
||||
synth_mmx.S, which the original comment about this being licensed under GPL is
|
||||
relating to.
|
||||
*/
|
||||
|
||||
/*
|
||||
* this code comes under GPL
|
||||
* This code was taken from http://www.mpg123.org
|
||||
* See ChangeLog of mpg123-0.59s-pre.1 for detail
|
||||
* Applied to mplayer by Nick Kurshev <nickols_k@mail.ru>
|
||||
|
@ -48,11 +49,25 @@ SYNTH_NAME:
|
|||
pushl %ebp
|
||||
/* stack:0=ebp 4=back 8=bandptr 12=channel 16=samples 20=buffs 24=bo 28=decwins */
|
||||
movl %esp, %ebp
|
||||
|
||||
/* Now the old stack addresses are preserved via %epb. */
|
||||
#ifdef PIC
|
||||
subl $8,%esp /* What has been called temp before. */
|
||||
#else
|
||||
subl $4,%esp /* What has been called temp before. */
|
||||
#endif
|
||||
pushl %edi
|
||||
pushl %esi
|
||||
pushl %ebx
|
||||
|
||||
#ifdef PIC
|
||||
#undef _EBX_
|
||||
#define _EBX_ %eax
|
||||
GET_GOT
|
||||
#define EBXSAVE -4(%ebp)
|
||||
movl _EBX_, EBXSAVE /* save PIC register */
|
||||
#endif
|
||||
|
||||
#define TEMP 12(%esp)
|
||||
/* APP */
|
||||
movl 12(%ebp),%ecx
|
||||
|
@ -94,6 +109,9 @@ SYNTH_NAME:
|
|||
leal (%ecx,%ebx,2), %edx
|
||||
movl (%esp),%ecx /* restore, but leave value on stack */
|
||||
shrl $1, %ecx
|
||||
#ifdef PIC
|
||||
movl EBXSAVE, _EBX_
|
||||
#endif
|
||||
ALIGN16
|
||||
3:
|
||||
movq (%edx),%mm0
|
||||
|
@ -130,8 +148,8 @@ SYNTH_NAME:
|
|||
packssdw %mm4,%mm4
|
||||
movq (%edi), %mm1
|
||||
punpckldq %mm4, %mm0
|
||||
pand one_null, %mm1
|
||||
pand null_one, %mm0
|
||||
pand LOCAL_VAR(one_null), %mm1
|
||||
pand LOCAL_VAR(null_one), %mm0
|
||||
por %mm0, %mm1
|
||||
movq %mm1,(%edi)
|
||||
leal 64(%esi),%esi
|
||||
|
@ -166,6 +184,10 @@ SYNTH_NAME:
|
|||
4:
|
||||
subl $64,%esi
|
||||
movl $7,%ecx
|
||||
|
||||
#ifdef PIC
|
||||
movl EBXSAVE, _EBX_
|
||||
#endif
|
||||
ALIGN16
|
||||
5:
|
||||
movq (%edx),%mm0
|
||||
|
@ -206,8 +228,8 @@ SYNTH_NAME:
|
|||
psubsw %mm5,%mm4
|
||||
movq (%edi), %mm1
|
||||
punpckldq %mm4, %mm0
|
||||
pand one_null, %mm1
|
||||
pand null_one, %mm0
|
||||
pand LOCAL_VAR(one_null), %mm1
|
||||
pand LOCAL_VAR(null_one), %mm0
|
||||
por %mm0, %mm1
|
||||
movq %mm1,(%edi)
|
||||
subl $64,%esi
|
||||
|
@ -241,6 +263,6 @@ SYNTH_NAME:
|
|||
popl %ebx
|
||||
popl %esi
|
||||
popl %edi
|
||||
addl $4,%esp
|
||||
mov %ebp, %esp
|
||||
popl %ebp
|
||||
ret
|
||||
|
|
|
@ -15,6 +15,7 @@ include_directories(BEFORE ${REACTOS_SOURCE_DIR}/sdk/include/reactos/libs/libmpg
|
|||
|
||||
list(APPEND SOURCE
|
||||
compat/compat.c
|
||||
compat/compat_str.c
|
||||
dct64.c
|
||||
dct64_i386.c
|
||||
equalizer.c
|
||||
|
|
669
reactos/sdk/lib/3rdparty/libmpg123/compat/compat.c
vendored
669
reactos/sdk/lib/3rdparty/libmpg123/compat/compat.c
vendored
|
@ -1,16 +1,665 @@
|
|||
/*
|
||||
Just to ensure that libraries and programs get their separate
|
||||
compatibility object. There should be a compatibility library,
|
||||
I presume, but I don't want to create another glib, I just want
|
||||
some internal functions to ease coding.
|
||||
compat: Some compatibility functions (basic memory & string stuff in separate file)
|
||||
|
||||
I'll sort it out properly sometime.
|
||||
The mpg123 code is determined to keep it's legacy. A legacy of old, old UNIX.
|
||||
So anything possibly somewhat advanced should be considered to be put here, with proper #ifdef;-)
|
||||
|
||||
I smell symbol conflicts, anyway. Actually wondering why it
|
||||
worked so far.
|
||||
copyright 2007-2016 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Thomas Orgis, Windows Unicode stuff by JonY.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "intsym.h"
|
||||
#define NO_CATCHSIGNAL
|
||||
#include "compat/compat_impl.h"
|
||||
/* This source file does need _POSIX_SOURCE to get some sigaction. */
|
||||
#define _POSIX_SOURCE
|
||||
#include "compat.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
|
||||
#if(defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP))
|
||||
#define WINDOWS_UWP
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#ifdef HAVE_SYS_STAT_H
|
||||
# include <sys/stat.h>
|
||||
#endif
|
||||
#ifdef HAVE_DIRENT_H
|
||||
# include <dirent.h>
|
||||
#endif
|
||||
|
||||
/* Win32 is only supported with unicode now. These headers also cover
|
||||
module stuff. The WANT_WIN32_UNICODE macro is synonymous with
|
||||
"want windows-specific API, and only the unicode variants of which". */
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
#include <wchar.h>
|
||||
#include <windows.h>
|
||||
#include <winnls.h>
|
||||
#include <shlwapi.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_MODULES
|
||||
# ifdef HAVE_DLFCN_H
|
||||
# include <dlfcn.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
#ifndef WINDOWS_UWP
|
||||
|
||||
char *compat_getenv(const char* name)
|
||||
{
|
||||
char *ret = NULL;
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
wchar_t *env;
|
||||
wchar_t *wname = NULL;
|
||||
if(win32_utf8_wide(name, &wname, NULL) > 0)
|
||||
{
|
||||
env = _wgetenv(wname);
|
||||
free(wname);
|
||||
if(env)
|
||||
win32_wide_utf8(env, &ret, NULL);
|
||||
}
|
||||
#else
|
||||
ret = getenv(name);
|
||||
if(ret)
|
||||
ret = compat_strdup(ret);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
|
||||
/* Convert unix UTF-8 (or ASCII) paths to Windows wide character paths. */
|
||||
static wchar_t* u2wpath(const char *upath)
|
||||
{
|
||||
wchar_t* wpath, *p;
|
||||
if(!upath || win32_utf8_wide(upath, &wpath, NULL) < 1)
|
||||
return NULL;
|
||||
for(p=wpath; *p; ++p)
|
||||
if(*p == L'/')
|
||||
*p = L'\\';
|
||||
return wpath;
|
||||
}
|
||||
|
||||
/* Convert Windows wide character paths to unix UTF-8. */
|
||||
static char* w2upath(const wchar_t *wpath)
|
||||
{
|
||||
char* upath, *p;
|
||||
if(!wpath || win32_wide_utf8(wpath, &upath, NULL) < 1)
|
||||
return NULL;
|
||||
for(p=upath; *p; ++p)
|
||||
if(*p == '\\')
|
||||
*p = '/';
|
||||
return upath;
|
||||
}
|
||||
|
||||
/* An absolute path that is too long and not already marked with
|
||||
\\?\ can be marked as a long one and still work. */
|
||||
static int wpath_need_elongation(wchar_t *wpath)
|
||||
{
|
||||
if( wpath && !PathIsRelativeW(wpath)
|
||||
&& wcslen(wpath) > MAX_PATH-1
|
||||
&& wcsncmp(L"\\\\?\\", wpath, 4) )
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Take any wide windows path and turn it into a path that is allowed
|
||||
to be longer than MAX_PATH, if it is not already. */
|
||||
static wchar_t* wlongpath(wchar_t *wpath)
|
||||
{
|
||||
size_t len, plen;
|
||||
const wchar_t *prefix = L"";
|
||||
wchar_t *wlpath = NULL;
|
||||
if(!wpath)
|
||||
return NULL;
|
||||
|
||||
/* Absolute paths that do not start with \\?\ get that prepended
|
||||
to allow them being long. */
|
||||
if(!PathIsRelativeW(wpath) && wcsncmp(L"\\\\?\\", wpath, 4))
|
||||
{
|
||||
if(wcslen(wpath) >= 2 && PathIsUNCW(wpath))
|
||||
{
|
||||
/* \\server\path -> \\?\UNC\server\path */
|
||||
prefix = L"\\\\?\\UNC";
|
||||
++wpath; /* Skip the first \. */
|
||||
}
|
||||
else /* c:\some/path -> \\?\c:\some\path */
|
||||
prefix = L"\\\\?\\";
|
||||
}
|
||||
plen = wcslen(prefix);
|
||||
len = plen + wcslen(wpath);
|
||||
wlpath = malloc(len+1*sizeof(wchar_t));
|
||||
if(wlpath)
|
||||
{
|
||||
/* Brute force memory copying, swprintf is too dandy. */
|
||||
memcpy(wlpath, prefix, sizeof(wchar_t)*plen);
|
||||
memcpy(wlpath+plen, wpath, sizeof(wchar_t)*(len-plen));
|
||||
wlpath[len] = 0;
|
||||
}
|
||||
return wlpath;
|
||||
}
|
||||
|
||||
/* Convert unix path to wide windows path, optionally marking
|
||||
it as long path if necessary. */
|
||||
static wchar_t* u2wlongpath(const char *upath)
|
||||
{
|
||||
wchar_t *wpath = NULL;
|
||||
wchar_t *wlpath = NULL;
|
||||
wpath = u2wpath(upath);
|
||||
if(wpath_need_elongation(wpath))
|
||||
{
|
||||
wlpath = wlongpath(wpath);
|
||||
free(wpath);
|
||||
wpath = wlpath;
|
||||
}
|
||||
return wpath;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
static wchar_t* u2wlongpath(const char *upath)
|
||||
{
|
||||
wchar_t* wpath, *p;
|
||||
if (!upath || win32_utf8_wide(upath, &wpath, NULL) < 1)
|
||||
return NULL;
|
||||
for (p = wpath; *p; ++p)
|
||||
if (*p == L'/')
|
||||
*p = L'\\';
|
||||
return wpath;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Always add a default permission mask in case of flags|O_CREAT. */
|
||||
int compat_open(const char *filename, int flags)
|
||||
{
|
||||
int ret;
|
||||
#if defined (WANT_WIN32_UNICODE)
|
||||
wchar_t *frag = NULL;
|
||||
|
||||
frag = u2wlongpath(filename);
|
||||
/* Fallback to plain open when ucs-2 conversion fails */
|
||||
if(!frag)
|
||||
goto open_fallback;
|
||||
|
||||
/*Try _wopen */
|
||||
ret = _wopen(frag, flags|_O_BINARY, _S_IREAD | _S_IWRITE);
|
||||
if(ret != -1 )
|
||||
goto open_ok; /* msdn says -1 means failure */
|
||||
|
||||
open_fallback:
|
||||
#endif
|
||||
|
||||
#if (defined(WIN32) && !defined (__CYGWIN__))
|
||||
/* MSDN says POSIX function is deprecated beginning in Visual C++ 2005 */
|
||||
/* Try plain old _open(), if it fails, do nothing */
|
||||
ret = _open(filename, flags|_O_BINARY, _S_IREAD | _S_IWRITE);
|
||||
#else
|
||||
ret = open(filename, flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
|
||||
#endif
|
||||
|
||||
#if defined (WANT_WIN32_UNICODE)
|
||||
open_ok:
|
||||
free(frag);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Moved over from wav.c, logic with fallbacks added from the
|
||||
example of compat_open(). */
|
||||
FILE* compat_fopen(const char *filename, const char *mode)
|
||||
{
|
||||
FILE* stream = NULL;
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
int cnt = 0;
|
||||
wchar_t *wname = NULL;
|
||||
wchar_t *wmode = NULL;
|
||||
|
||||
wname = u2wlongpath(filename);
|
||||
if(!wname)
|
||||
goto fopen_fallback;
|
||||
cnt = win32_utf8_wide(mode, &wmode, NULL);
|
||||
if( (wmode == NULL) || (cnt == 0))
|
||||
goto fopen_fallback;
|
||||
|
||||
stream = _wfopen(wname, wmode);
|
||||
if(stream) goto fopen_ok;
|
||||
|
||||
fopen_fallback:
|
||||
#endif
|
||||
stream = fopen(filename, mode);
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
|
||||
fopen_ok:
|
||||
free(wmode);
|
||||
free(wname);
|
||||
#endif
|
||||
return stream;
|
||||
}
|
||||
|
||||
FILE* compat_fdopen(int fd, const char *mode)
|
||||
{
|
||||
return fdopen(fd, mode);
|
||||
}
|
||||
|
||||
int compat_close(int infd)
|
||||
{
|
||||
#if (defined(WIN32) && !defined (__CYGWIN__)) /* MSDN says POSIX function is deprecated beginning in Visual C++ 2005 */
|
||||
return _close(infd);
|
||||
#else
|
||||
return close(infd);
|
||||
#endif
|
||||
}
|
||||
|
||||
int compat_fclose(FILE *stream)
|
||||
{
|
||||
return fclose(stream);
|
||||
}
|
||||
|
||||
/* Windows Unicode stuff */
|
||||
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
int win32_wide_utf8(const wchar_t * const wptr, char **mbptr, size_t * buflen)
|
||||
{
|
||||
size_t len;
|
||||
char *buf;
|
||||
int ret = 0;
|
||||
|
||||
len = WideCharToMultiByte(CP_UTF8, 0, wptr, -1, NULL, 0, NULL, NULL); /* Get utf-8 string length */
|
||||
buf = calloc(len + 1, sizeof (char)); /* Can we assume sizeof char always = 1? */
|
||||
|
||||
if(!buf) len = 0;
|
||||
else {
|
||||
if (len != 0) ret = WideCharToMultiByte(CP_UTF8, 0, wptr, -1, buf, len, NULL, NULL); /*Do actual conversion*/
|
||||
buf[len] = '0'; /* Must terminate */
|
||||
}
|
||||
*mbptr = buf; /* Set string pointer to allocated buffer */
|
||||
if(buflen != NULL) *buflen = (len) * sizeof (char); /* Give length of allocated memory if needed. */
|
||||
return ret;
|
||||
}
|
||||
|
||||
int win32_utf8_wide(const char *const mbptr, wchar_t **wptr, size_t *buflen)
|
||||
{
|
||||
size_t len;
|
||||
wchar_t *buf;
|
||||
int ret = 0;
|
||||
|
||||
len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mbptr, -1, NULL, 0); /* Get converted size */
|
||||
buf = calloc(len + 1, sizeof (wchar_t)); /* Allocate memory accordingly */
|
||||
|
||||
if(!buf) len = 0;
|
||||
else {
|
||||
if (len != 0) ret = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, mbptr, -1, buf, len); /* Do conversion */
|
||||
buf[len] = L'0'; /* Must terminate */
|
||||
}
|
||||
*wptr = buf; /* Set string pointer to allocated buffer */
|
||||
if (buflen != NULL) *buflen = len * sizeof (wchar_t); /* Give length of allocated memory if needed. */
|
||||
return ret; /* Number of characters written */
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef WINDOWS_UWP
|
||||
|
||||
/*
|
||||
The Windows file and path stuff is an extract of jon_y's win32 loader
|
||||
prototype from the loader_rework branch. It's been divided in to
|
||||
reusable functons by ThOr in the hope to work out some generic-looking
|
||||
loader code for both POSIX and Windows. The routines might be
|
||||
helpful for consistent path work in other parts of mpg123, too.
|
||||
|
||||
This all is about getting some working code on a wide range of
|
||||
systems while staying somewhat sane. If it does ridiculously inefficient
|
||||
things with extraneous copies and grabbing of functions that made
|
||||
it late to some official APIs, that's still fine with us.
|
||||
*/
|
||||
|
||||
char* compat_catpath(const char *prefix, const char* path)
|
||||
{
|
||||
char *ret = NULL;
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
wchar_t *wprefix = NULL; /* Wide windows versions of */
|
||||
wchar_t *wpath = NULL; /* input arguments. */
|
||||
wchar_t *locwret = NULL; /* Tmp return value from LocalAlloc */
|
||||
/*
|
||||
This variation of combinepath can work with long and UNC paths, but
|
||||
is not officially exposed in any DLLs, It also allocates all its buffers
|
||||
internally via LocalAlloc, avoiding buffer overflow problems.
|
||||
ThOr: I presume this hack is for supporting pre-8 Windows, as
|
||||
from Windows 8 on, this is documented in the API.
|
||||
*/
|
||||
HRESULT (__stdcall *mypac)( const wchar_t *in, const wchar_t* more
|
||||
, unsigned long flags, wchar_t **out ) = NULL;
|
||||
HMODULE pathcch = NULL;
|
||||
|
||||
if(!prefix && !path)
|
||||
goto catpath_end;
|
||||
wprefix = u2wpath(prefix);
|
||||
wpath = u2wpath(path);
|
||||
if((prefix && !wprefix) || (path && !wpath))
|
||||
goto catpath_end;
|
||||
|
||||
/* Again: I presume this whole fun is to get at PathAllocCombine
|
||||
even when pathcch.h is not available (like in MinGW32). */
|
||||
if( (pathcch = GetModuleHandleA("kernelbase")) )
|
||||
mypac = (void *)GetProcAddress(pathcch, "PathAllocCombine");
|
||||
if(mypac) /* PATHCCH_ALLOW_LONG_PATH = 1 per API docs */
|
||||
{
|
||||
debug("Actually calling PathAllocCombine!");
|
||||
mypac(wprefix, wpath, 1, &locwret);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Playing safe, if we'd care much about performance, this would be on
|
||||
the stack. */
|
||||
locwret = LocalAlloc(LPTR, sizeof(wchar_t)*MAX_PATH);
|
||||
if(locwret)
|
||||
PathCombineW(locwret, wprefix, wpath);
|
||||
}
|
||||
ret = w2upath(locwret);
|
||||
|
||||
catpath_end:
|
||||
LocalFree(locwret);
|
||||
free(wprefix);
|
||||
free(wpath);
|
||||
#else
|
||||
size_t len, prelen, patlen;
|
||||
|
||||
if(path && path[0] == '/')
|
||||
prefix = NULL; /* Absolute path stays as it is. */
|
||||
prelen = prefix ? strlen(prefix) : 0;
|
||||
patlen = path ? strlen(path) : 0;
|
||||
/* Concatenate the two, put a / in between if both present. */
|
||||
len = ((prefix && path) ? 1 : 0) + prelen + patlen;
|
||||
ret = malloc(len+1);
|
||||
if(ret)
|
||||
{
|
||||
size_t off=0;
|
||||
memcpy(ret, prefix, prelen);
|
||||
if(prefix && path)
|
||||
ret[prelen+(off++)] = '/';
|
||||
memcpy(ret+prelen+off, path, patlen);
|
||||
ret[len] = 0;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int compat_isdir(const char *path)
|
||||
{
|
||||
int ret = 0;
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
wchar_t *wpath;
|
||||
wpath = u2wlongpath(path);
|
||||
if(wpath)
|
||||
{
|
||||
DWORD attr = GetFileAttributesW(wpath);
|
||||
if(attr != INVALID_FILE_ATTRIBUTES && attr & FILE_ATTRIBUTE_DIRECTORY)
|
||||
ret=1;
|
||||
free(wpath);
|
||||
}
|
||||
#else
|
||||
struct stat sb;
|
||||
if(path && !stat(path, &sb))
|
||||
{
|
||||
if(S_ISDIR(sb.st_mode))
|
||||
ret=1;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct compat_dir
|
||||
{
|
||||
char *path;
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
int gotone; /* Got a result stored from FindFirstFileW. */
|
||||
WIN32_FIND_DATAW d;
|
||||
HANDLE ffn;
|
||||
#else
|
||||
DIR* dir;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct compat_dir* compat_diropen(char *path)
|
||||
{
|
||||
struct compat_dir *cd;
|
||||
if(!path)
|
||||
return NULL;
|
||||
cd = malloc(sizeof(*cd));
|
||||
if(!cd)
|
||||
return NULL;
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
cd->gotone = 0;
|
||||
{
|
||||
char *pattern;
|
||||
wchar_t *wpattern;
|
||||
pattern = compat_catpath(path, "*");
|
||||
wpattern = u2wlongpath(pattern);
|
||||
if(wpattern)
|
||||
{
|
||||
cd->ffn = FindFirstFileW(wpattern, &(cd->d));
|
||||
if(cd->ffn == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/* FindClose() only needed after successful first find, right? */
|
||||
free(cd);
|
||||
cd = NULL;
|
||||
}
|
||||
else
|
||||
cd->gotone = 1;
|
||||
}
|
||||
free(wpattern);
|
||||
free(pattern);
|
||||
}
|
||||
#else
|
||||
cd->dir = opendir(path);
|
||||
if(!cd->dir)
|
||||
{
|
||||
free(cd);
|
||||
cd = NULL;
|
||||
}
|
||||
#endif
|
||||
if(cd)
|
||||
{
|
||||
cd->path = compat_strdup(path);
|
||||
if(!cd->path)
|
||||
{
|
||||
compat_dirclose(cd);
|
||||
cd = NULL;
|
||||
}
|
||||
}
|
||||
return cd;
|
||||
}
|
||||
|
||||
void compat_dirclose(struct compat_dir *cd)
|
||||
{
|
||||
if(cd)
|
||||
{
|
||||
free(cd->path);
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
FindClose(cd->ffn);
|
||||
#else
|
||||
closedir(cd->dir);
|
||||
#endif
|
||||
free(cd);
|
||||
}
|
||||
}
|
||||
|
||||
char* compat_nextfile(struct compat_dir *cd)
|
||||
{
|
||||
if(!cd)
|
||||
return NULL;
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
while(cd->gotone || FindNextFileW(cd->ffn, &(cd->d)))
|
||||
{
|
||||
cd->gotone = 0;
|
||||
if(!(cd->d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
|
||||
{
|
||||
char *ret;
|
||||
win32_wide_utf8(cd->d.cFileName, &ret, NULL);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
struct dirent *dp;
|
||||
while((dp = readdir(cd->dir)))
|
||||
{
|
||||
struct stat fst;
|
||||
char *fullpath = compat_catpath(cd->path, dp->d_name);
|
||||
if(fullpath && !stat(fullpath, &fst) && S_ISREG(fst.st_mode))
|
||||
{
|
||||
free(fullpath);
|
||||
return compat_strdup(dp->d_name);
|
||||
}
|
||||
free(fullpath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char* compat_nextdir(struct compat_dir *cd)
|
||||
{
|
||||
if(!cd)
|
||||
return NULL;
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
while(cd->gotone || FindNextFileW(cd->ffn, &(cd->d)))
|
||||
{
|
||||
cd->gotone = 0;
|
||||
if(cd->d.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
|
||||
{
|
||||
char *ret;
|
||||
win32_wide_utf8(cd->d.cFileName, &ret, NULL);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
#else
|
||||
{
|
||||
struct dirent *dp;
|
||||
while((dp = readdir(cd->dir)))
|
||||
{
|
||||
struct stat fst;
|
||||
char *fullpath = compat_catpath(cd->path, dp->d_name);
|
||||
if(fullpath && !stat(fullpath, &fst) && S_ISDIR(fst.st_mode))
|
||||
{
|
||||
free(fullpath);
|
||||
return compat_strdup(dp->d_name);
|
||||
}
|
||||
free(fullpath);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_MODULES
|
||||
/*
|
||||
This is what I expected the platform-specific dance for dynamic module
|
||||
support to be. Little did I know about the peculiarities of (long)
|
||||
paths and directory/file search on Windows.
|
||||
*/
|
||||
|
||||
void *compat_dlopen(const char *path)
|
||||
{
|
||||
void *handle = NULL;
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
wchar_t *wpath;
|
||||
wpath = u2wlongpath(path);
|
||||
if(wpath)
|
||||
handle = LoadLibraryW(wpath);
|
||||
free(wpath);
|
||||
#else
|
||||
handle = dlopen(path, RTLD_NOW);
|
||||
#endif
|
||||
return handle;
|
||||
}
|
||||
|
||||
void *compat_dlsym(void *handle, const char *name)
|
||||
{
|
||||
void *sym = NULL;
|
||||
if(!handle)
|
||||
return NULL;
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
sym = GetProcAddress(handle, name);
|
||||
#else
|
||||
sym = dlsym(handle, name);
|
||||
#endif
|
||||
return sym;
|
||||
}
|
||||
|
||||
void compat_dlclose(void *handle)
|
||||
{
|
||||
if(!handle)
|
||||
return;
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
FreeLibrary(handle);
|
||||
#else
|
||||
dlclose(handle);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* USE_MODULES */
|
||||
|
||||
|
||||
/* This shall survive signals and any return value less than given byte count
|
||||
is an error */
|
||||
size_t unintr_write(int fd, void const *buffer, size_t bytes)
|
||||
{
|
||||
size_t written = 0;
|
||||
while(bytes)
|
||||
{
|
||||
ssize_t part = write(fd, (char*)buffer+written, bytes);
|
||||
if(part < 0 && errno != EINTR)
|
||||
break;
|
||||
bytes -= part;
|
||||
written += part;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
/* Same for reading the data. */
|
||||
size_t unintr_read(int fd, void *buffer, size_t bytes)
|
||||
{
|
||||
size_t got = 0;
|
||||
while(bytes)
|
||||
{
|
||||
ssize_t part = read(fd, (char*)buffer+got, bytes);
|
||||
if(part < 0 && errno != EINTR)
|
||||
break;
|
||||
bytes -= part;
|
||||
got += part;
|
||||
}
|
||||
return got;
|
||||
}
|
||||
|
||||
#ifndef NO_CATCHSIGNAL
|
||||
#if (!defined(WIN32) || defined (__CYGWIN__)) && defined(HAVE_SIGNAL_H)
|
||||
void (*catchsignal(int signum, void(*handler)()))()
|
||||
{
|
||||
struct sigaction new_sa;
|
||||
struct sigaction old_sa;
|
||||
|
||||
#ifdef DONT_CATCH_SIGNALS
|
||||
fprintf (stderr, "Not catching any signals.\n");
|
||||
return ((void (*)()) -1);
|
||||
#endif
|
||||
|
||||
new_sa.sa_handler = handler;
|
||||
sigemptyset(&new_sa.sa_mask);
|
||||
new_sa.sa_flags = 0;
|
||||
if(sigaction(signum, &new_sa, &old_sa) == -1)
|
||||
return ((void (*)()) -1);
|
||||
return (old_sa.sa_handler);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -1,236 +0,0 @@
|
|||
/*
|
||||
compat: Some compatibility functions.
|
||||
|
||||
The mpg123 code is determined to keep it's legacy. A legacy of old, old UNIX.
|
||||
So anything possibly somewhat advanced should be considered to be put here, with proper #ifdef;-)
|
||||
|
||||
copyright 2007-8 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Thomas Orgis, Windows Unicode stuff by JonY.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "compat.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
#include <wchar.h>
|
||||
#include <windows.h>
|
||||
#include <winnls.h>
|
||||
#endif
|
||||
|
||||
#include "debug.h"
|
||||
|
||||
/* A safe realloc also for very old systems where realloc(NULL, size) returns NULL. */
|
||||
void *safe_realloc(void *ptr, size_t size)
|
||||
{
|
||||
if(ptr == NULL) return malloc(size);
|
||||
else return realloc(ptr, size);
|
||||
}
|
||||
|
||||
#ifndef HAVE_STRERROR
|
||||
const char *strerror(int errnum)
|
||||
{
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
|
||||
return (errnum < sys_nerr) ? sys_errlist[errnum] : "";
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRDUP
|
||||
char *strdup(const char *src)
|
||||
{
|
||||
char *dest;
|
||||
|
||||
if (!(dest = (char *) malloc(strlen(src)+1)))
|
||||
return NULL;
|
||||
else
|
||||
return strcpy(dest, src);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Always add a default permission mask in case of flags|O_CREAT. */
|
||||
int compat_open(const char *filename, int flags)
|
||||
{
|
||||
int ret;
|
||||
#if defined (WANT_WIN32_UNICODE)
|
||||
wchar_t *frag = NULL;
|
||||
|
||||
ret = win32_utf8_wide(filename, &frag, NULL);
|
||||
/* Fallback to plain open when ucs-2 conversion fails */
|
||||
if((frag == NULL) || (ret == 0))
|
||||
goto open_fallback;
|
||||
|
||||
/*Try _wopen */
|
||||
ret = _wopen(frag, flags|_O_BINARY, _S_IREAD | _S_IWRITE);
|
||||
if(ret != -1 )
|
||||
goto open_ok; /* msdn says -1 means failure */
|
||||
|
||||
open_fallback:
|
||||
#endif
|
||||
|
||||
#if (defined(WIN32) && !defined (__CYGWIN__))
|
||||
/* MSDN says POSIX function is deprecated beginning in Visual C++ 2005 */
|
||||
/* Try plain old _open(), if it fails, do nothing */
|
||||
ret = _open(filename, flags|_O_BINARY, _S_IREAD | _S_IWRITE);
|
||||
#else
|
||||
ret = open(filename, flags, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH);
|
||||
#endif
|
||||
|
||||
#if defined (WANT_WIN32_UNICODE)
|
||||
open_ok:
|
||||
/* A cast to void*? Does Windows need that?! */
|
||||
free((void *)frag);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Moved over from wav.c, logic with fallbacks added from the
|
||||
example of compat_open(). */
|
||||
FILE* compat_fopen(const char *filename, const char *mode)
|
||||
{
|
||||
FILE* stream = NULL;
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
int cnt = 0;
|
||||
wchar_t *wname = NULL;
|
||||
wchar_t *wmode = NULL;
|
||||
|
||||
cnt = win32_utf8_wide(filename, &wname, NULL);
|
||||
if( (wname == NULL) || (cnt == 0))
|
||||
goto fopen_fallback;
|
||||
cnt = win32_utf8_wide(mode, &wmode, NULL);
|
||||
if( (wmode == NULL) || (cnt == 0))
|
||||
goto fopen_fallback;
|
||||
|
||||
stream = _wfopen(wname, wmode);
|
||||
if(stream) goto fopen_ok;
|
||||
|
||||
fopen_fallback:
|
||||
#endif
|
||||
stream = fopen(filename, mode);
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
|
||||
fopen_ok:
|
||||
free(wmode);
|
||||
free(wname);
|
||||
#endif
|
||||
return stream;
|
||||
}
|
||||
|
||||
int compat_close(int infd)
|
||||
{
|
||||
#if (defined(WIN32) && !defined (__CYGWIN__)) /* MSDN says POSIX function is deprecated beginning in Visual C++ 2005 */
|
||||
return _close(infd);
|
||||
#else
|
||||
return close(infd);
|
||||
#endif
|
||||
}
|
||||
|
||||
int compat_fclose(FILE *stream)
|
||||
{
|
||||
return fclose(stream);
|
||||
}
|
||||
|
||||
/* Windows Unicode stuff */
|
||||
|
||||
#ifdef WANT_WIN32_UNICODE
|
||||
int win32_wide_utf8(const wchar_t * const wptr, char **mbptr, size_t * buflen)
|
||||
{
|
||||
size_t len;
|
||||
char *buf;
|
||||
int ret = 0;
|
||||
|
||||
len = WideCharToMultiByte(CP_UTF8, 0, wptr, -1, NULL, 0, NULL, NULL); /* Get utf-8 string length */
|
||||
buf = calloc(len + 1, sizeof (char)); /* Can we assume sizeof char always = 1? */
|
||||
|
||||
if(!buf) len = 0;
|
||||
else {
|
||||
if (len != 0) ret = WideCharToMultiByte(CP_UTF8, 0, wptr, -1, buf, len, NULL, NULL); /*Do actual conversion*/
|
||||
buf[len] = '0'; /* Must terminate */
|
||||
}
|
||||
*mbptr = buf; /* Set string pointer to allocated buffer */
|
||||
if(buflen != NULL) *buflen = (len) * sizeof (char); /* Give length of allocated memory if needed. */
|
||||
return ret;
|
||||
}
|
||||
|
||||
int win32_utf8_wide(const char *const mbptr, wchar_t **wptr, size_t *buflen)
|
||||
{
|
||||
size_t len;
|
||||
wchar_t *buf;
|
||||
int ret = 0;
|
||||
|
||||
len = MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mbptr, -1, NULL, 0); /* Get converted size */
|
||||
buf = calloc(len + 1, sizeof (wchar_t)); /* Allocate memory accordingly */
|
||||
|
||||
if(!buf) len = 0;
|
||||
else {
|
||||
if (len != 0) ret = MultiByteToWideChar (CP_UTF8, MB_ERR_INVALID_CHARS, mbptr, -1, buf, len); /* Do conversion */
|
||||
buf[len] = L'0'; /* Must terminate */
|
||||
}
|
||||
*wptr = buf; /* Set string pointer to allocated buffer */
|
||||
if (buflen != NULL) *buflen = len * sizeof (wchar_t); /* Give length of allocated memory if needed. */
|
||||
return ret; /* Number of characters written */
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* This shall survive signals and any return value less than given byte count
|
||||
is an error */
|
||||
size_t unintr_write(int fd, void const *buffer, size_t bytes)
|
||||
{
|
||||
size_t written = 0;
|
||||
while(bytes)
|
||||
{
|
||||
ssize_t part = write(fd, (char*)buffer+written, bytes);
|
||||
if(part < 0 && errno != EINTR)
|
||||
break;
|
||||
bytes -= part;
|
||||
written += part;
|
||||
}
|
||||
return written;
|
||||
}
|
||||
|
||||
/* Same for reading the data. */
|
||||
size_t unintr_read(int fd, void *buffer, size_t bytes)
|
||||
{
|
||||
size_t got = 0;
|
||||
while(bytes)
|
||||
{
|
||||
ssize_t part = read(fd, (char*)buffer+got, bytes);
|
||||
if(part < 0 && errno != EINTR)
|
||||
break;
|
||||
bytes -= part;
|
||||
got += part;
|
||||
}
|
||||
return got;
|
||||
}
|
||||
|
||||
#ifndef NO_CATCHSIGNAL
|
||||
#if (!defined(WIN32) || defined (__CYGWIN__)) && defined(HAVE_SIGNAL_H)
|
||||
void (*catchsignal(int signum, void(*handler)()))()
|
||||
{
|
||||
struct sigaction new_sa;
|
||||
struct sigaction old_sa;
|
||||
|
||||
#ifdef DONT_CATCH_SIGNALS
|
||||
fprintf (stderr, "Not catching any signals.\n");
|
||||
return ((void (*)()) -1);
|
||||
#endif
|
||||
|
||||
new_sa.sa_handler = handler;
|
||||
sigemptyset(&new_sa.sa_mask);
|
||||
new_sa.sa_flags = 0;
|
||||
if(sigaction(signum, &new_sa, &old_sa) == -1)
|
||||
return ((void (*)()) -1);
|
||||
return (old_sa.sa_handler);
|
||||
}
|
||||
#endif
|
||||
#endif
|
43
reactos/sdk/lib/3rdparty/libmpg123/compat/compat_str.c
vendored
Normal file
43
reactos/sdk/lib/3rdparty/libmpg123/compat/compat_str.c
vendored
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
compat: Some compatibility functions (basic memory and string stuff)
|
||||
|
||||
The mpg123 code is determined to keep it's legacy. A legacy of old, old UNIX.
|
||||
So anything possibly somewhat advanced should be considered to be put here, with proper #ifdef;-)
|
||||
|
||||
copyright 2007-2016 by the mpg123 project - free software under the terms of the LGPL 2.1
|
||||
see COPYING and AUTHORS files in distribution or http://mpg123.org
|
||||
initially written by Thomas Orgis, Windows Unicode stuff by JonY.
|
||||
*/
|
||||
|
||||
#include "compat.h"
|
||||
#include "debug.h"
|
||||
|
||||
/* A safe realloc also for very old systems where realloc(NULL, size) returns NULL. */
|
||||
void *safe_realloc(void *ptr, size_t size)
|
||||
{
|
||||
if(ptr == NULL) return malloc(size);
|
||||
else return realloc(ptr, size);
|
||||
}
|
||||
|
||||
#ifndef HAVE_STRERROR
|
||||
const char *strerror(int errnum)
|
||||
{
|
||||
extern int sys_nerr;
|
||||
extern char *sys_errlist[];
|
||||
|
||||
return (errnum < sys_nerr) ? sys_errlist[errnum] : "";
|
||||
}
|
||||
#endif
|
||||
|
||||
char* compat_strdup(const char *src)
|
||||
{
|
||||
char *dest = NULL;
|
||||
if(src)
|
||||
{
|
||||
size_t len;
|
||||
len = strlen(src)+1;
|
||||
if((dest = malloc(len)))
|
||||
memcpy(dest, src, len);
|
||||
}
|
||||
return dest;
|
||||
}
|
|
@ -384,7 +384,7 @@ icy2utf8(const char *src, int force)
|
|||
|
||||
/* Some funny streams from Apple/iTunes give ICY info in UTF-8 already.
|
||||
So, be prepared and don't try to re-encode such. Unless forced. */
|
||||
if(!force && is_utf8(src)) return (strdup(src));
|
||||
if(!force && is_utf8(src)) return (compat_strdup(src));
|
||||
|
||||
srclen = strlen(src) + 1;
|
||||
/* allocate conservatively */
|
||||
|
|
32
reactos/sdk/lib/3rdparty/libmpg123/id3.c
vendored
32
reactos/sdk/lib/3rdparty/libmpg123/id3.c
vendored
|
@ -656,6 +656,9 @@ int parse_new_id3(mpg123_handle *fr, unsigned long first4bytes)
|
|||
unsigned char flags = 0;
|
||||
int ret = 1;
|
||||
int ret2;
|
||||
#ifndef NO_ID3V2
|
||||
int skiptag = 0;
|
||||
#endif
|
||||
unsigned char major = first4bytes & 0xff;
|
||||
debug1("ID3v2: major tag version: %i", major);
|
||||
if(major == 0xff) return 0; /* Invalid... */
|
||||
|
@ -706,17 +709,28 @@ int parse_new_id3(mpg123_handle *fr, unsigned long first4bytes)
|
|||
#ifndef NO_ID3V2
|
||||
if(VERBOSE2) fprintf(stderr,"Note: ID3v2.%i rev %i tag of %lu bytes\n", major, buf[0], length);
|
||||
/* skip if unknown version/scary flags, parse otherwise */
|
||||
if(fr->p.flags & MPG123_SKIP_ID3V2 || ((flags & UNKNOWN_FLAGS) || (major > 4) || (major < 2)))
|
||||
if(fr->p.flags & MPG123_SKIP_ID3V2)
|
||||
{
|
||||
if(VERBOSE3)
|
||||
fprintf(stderr, "Note: Skipping ID3v2 tag per user request.\n");
|
||||
skiptag = 1;
|
||||
}
|
||||
if((flags & UNKNOWN_FLAGS) || (major > 4) || (major < 2))
|
||||
{
|
||||
if(NOQUIET)
|
||||
{
|
||||
if(fr->p.flags & MPG123_SKIP_ID3V2)
|
||||
{
|
||||
if(VERBOSE3) fprintf(stderr, "Note: Skipping ID3v2 tag per user request.\n");
|
||||
}
|
||||
else /* Must be because of scary Tag properties. */
|
||||
warning2("ID3v2: Won't parse the ID3v2 tag with major version %u and flags 0x%xu - some extra code may be needed", major, flags);
|
||||
}
|
||||
warning2( "ID3v2: Won't parse the ID3v2 tag with major version"
|
||||
" %u and flags 0x%xu - some extra code may be needed"
|
||||
, major, flags );
|
||||
skiptag = 1;
|
||||
}
|
||||
if(length < 10)
|
||||
{
|
||||
if(NOQUIET)
|
||||
warning1("ID3v2: unrealistic small tag lengh %lu, skipping", length);
|
||||
skiptag = 1;
|
||||
}
|
||||
if(skiptag)
|
||||
{
|
||||
#endif
|
||||
if((ret2 = fr->rd->skip_bytes(fr,length)) < 0) /* will not store data in backbuff! */
|
||||
ret = ret2;
|
||||
|
|
24
reactos/sdk/lib/3rdparty/libmpg123/libmpg123.c
vendored
24
reactos/sdk/lib/3rdparty/libmpg123/libmpg123.c
vendored
|
@ -11,6 +11,9 @@
|
|||
#include "debug.h"
|
||||
|
||||
#include "gapless.h"
|
||||
/* Want accurate rounding function regardless of decoder setup. */
|
||||
#define FORCE_ACCURATE
|
||||
#include "sample.h"
|
||||
|
||||
#define SEEKFRAME(mh) ((mh)->ignoreframe < 0 ? 0 : (mh)->ignoreframe)
|
||||
|
||||
|
@ -31,6 +34,15 @@ int attribute_align_arg mpg123_init(void)
|
|||
prepare_decode_tables();
|
||||
check_decoders();
|
||||
initialized = 1;
|
||||
#if (defined REAL_IS_FLOAT) && (defined IEEE_FLOAT)
|
||||
/* This is rather pointless but it eases my mind to check that we did
|
||||
not enable the special rounding on a VAX or something. */
|
||||
if(12346 != REAL_TO_SHORT_ACCURATE(12345.67f))
|
||||
{
|
||||
error("Bad IEEE 754 rounding. Re-build libmpg123 properly.");
|
||||
return MPG123_ERR;
|
||||
}
|
||||
#endif
|
||||
return MPG123_OK;
|
||||
}
|
||||
|
||||
|
@ -357,7 +369,7 @@ int attribute_align_arg mpg123_getstate(mpg123_handle *mh, enum mpg123_state key
|
|||
{
|
||||
size_t sval = bc_fill(&mh->rdat.buffer);
|
||||
theval = (long)sval;
|
||||
if((size_t)theval != sval)
|
||||
if(theval < 0 || (size_t)theval != sval)
|
||||
{
|
||||
mh->err = MPG123_INT_OVERFLOW;
|
||||
ret = MPG123_ERR;
|
||||
|
@ -1035,7 +1047,8 @@ int attribute_align_arg mpg123_info(mpg123_handle *mh, struct mpg123_frameinfo *
|
|||
return MPG123_OK;
|
||||
}
|
||||
|
||||
int attribute_align_arg mpg123_getformat(mpg123_handle *mh, long *rate, int *channels, int *encoding)
|
||||
int attribute_align_arg mpg123_getformat2( mpg123_handle *mh
|
||||
, long *rate, int *channels, int *encoding, int clear_flag )
|
||||
{
|
||||
int b;
|
||||
|
||||
|
@ -1046,10 +1059,15 @@ int attribute_align_arg mpg123_getformat(mpg123_handle *mh, long *rate, int *cha
|
|||
if(rate != NULL) *rate = mh->af.rate;
|
||||
if(channels != NULL) *channels = mh->af.channels;
|
||||
if(encoding != NULL) *encoding = mh->af.encoding;
|
||||
mh->new_format = 0;
|
||||
if(clear_flag) mh->new_format = 0;
|
||||
return MPG123_OK;
|
||||
}
|
||||
|
||||
int attribute_align_arg mpg123_getformat(mpg123_handle *mh, long *rate, int *channels, int *encoding)
|
||||
{
|
||||
return mpg123_getformat2(mh, rate, channels, encoding, 1);
|
||||
}
|
||||
|
||||
off_t attribute_align_arg mpg123_timeframe(mpg123_handle *mh, double seconds)
|
||||
{
|
||||
off_t b;
|
||||
|
|
4
reactos/sdk/lib/3rdparty/libmpg123/readers.c
vendored
4
reactos/sdk/lib/3rdparty/libmpg123/readers.c
vendored
|
@ -1049,8 +1049,10 @@ static int default_init(mpg123_handle *fr)
|
|||
if(fr->p.icy_interval > 0) fr->rdat.lseek = nix_lseek;
|
||||
#endif
|
||||
|
||||
fr->rdat.filelen = get_fileinfo(fr);
|
||||
fr->rdat.filelen = fr->p.flags & MPG123_NO_PEEK_END ? -1 : get_fileinfo(fr);
|
||||
fr->rdat.filepos = 0;
|
||||
if(fr->p.flags & MPG123_FORCE_SEEKABLE)
|
||||
fr->rdat.flags |= READER_SEEKABLE;
|
||||
/*
|
||||
Don't enable seeking on ICY streams, just plain normal files.
|
||||
This check is necessary since the client can enforce ICY parsing on files that would otherwise be seekable.
|
||||
|
|
3
reactos/sdk/lib/3rdparty/libmpg123/synth.c
vendored
3
reactos/sdk/lib/3rdparty/libmpg123/synth.c
vendored
|
@ -7,6 +7,9 @@
|
|||
*/
|
||||
|
||||
#include "mpg123lib_intern.h"
|
||||
#ifdef OPT_GENERIC_DITHER
|
||||
#define FORCE_ACCURATE
|
||||
#endif
|
||||
#include "sample.h"
|
||||
#include "debug.h"
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue