From 24be34f1e9e37111a06108c090324426aff6f1db Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 27 Feb 2012 19:15:13 +0100 Subject: cleanup: Silence compilation warnings on MinGW-w64 Some of the code, especially the dshow and windows codec loader parts, are extremely hacky and likely full of bugs. The goal is merely getting rid of warnings that could obscure more important warnings and actual bugs, instead of fixing actual problems. This reduces the number of warnings from over 500 to almost the same as when compiling on Linux. Note that many problems stem from using the ancient wine-derived windows headers. There are some differences to the "proper" windows header. Changing the code to compile with the proper headers would be too much trouble, and it still has to work on Unix. Some of the changes might actually break compilation on legacy MinGW, but we don't support that anymore. Always use MinGW-w64, even when compiling to 32 bit. Fixes some warnings in the win32 loader code on Linux too. --- osdep/getch2-win.c | 4 ++-- osdep/setenv.c | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'osdep') diff --git a/osdep/getch2-win.c b/osdep/getch2-win.c index 0b4d2b0bae..3e6eeff086 100644 --- a/osdep/getch2-win.c +++ b/osdep/getch2-win.c @@ -77,7 +77,7 @@ static int getch2_internal(void) /*check if there are input events*/ if(!GetNumberOfConsoleInputEvents(in,&retval)) { - printf("getch2: can't get number of input events: %i\n",GetLastError()); + printf("getch2: can't get number of input events: %i\n",(int)GetLastError()); return -1; } if(retval<=0)return -1; @@ -165,7 +165,7 @@ void getch2_enable(void) in = GetStdHandle(STD_INPUT_HANDLE); if(!GetNumberOfConsoleInputEvents(in,&retval)) { - printf("getch2: %i can't get number of input events [disabling console input]\n",GetLastError()); + printf("getch2: %i can't get number of input events [disabling console input]\n",(int)GetLastError()); getch2_status = 0; } else getch2_status=1; diff --git a/osdep/setenv.c b/osdep/setenv.c index 9919fff2a3..222d3ba82b 100644 --- a/osdep/setenv.c +++ b/osdep/setenv.c @@ -24,6 +24,8 @@ #include #include +int setenv(const char *name, const char *val, int overwrite); + int setenv(const char *name, const char *val, int overwrite) { int len = strlen(name) + strlen(val) + 2; -- cgit v1.2.3 From a1244111a790bbc4bf91b078ebcad3f415da79da Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 3 Feb 2012 08:05:11 +0100 Subject: windows support: unicode filenames Windows uses a legacy codepage for char* / runtime functions accepting char *. Using UTF-8 as the codepage with setlocale() is explicitly forbidden. Work this around by overriding the MSVCRT functions with wrapper macros, that assume UTF-8 and use "proper" API calls like _wopen etc. to deal with unicode filenames. All code that uses standard functions that take or return filenames must now include osdep/io.h. stat() can't be overridden, because MinGW-w64 itself defines "stat" as a macro. Change code to use use mp_stat() instead. This is not perfectly clean, but still somewhat sane, and much better than littering the rest of the mplayer code with MinGW specific hacks. It's also a bit fragile, but that's actually little different from the previous situation. Also, MinGW is unlikely to ever include a nice way of dealing with this. --- osdep/io.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ osdep/io.h | 76 +++++++++++++++++++++++++ 2 files changed, 261 insertions(+) create mode 100644 osdep/io.c create mode 100644 osdep/io.h (limited to 'osdep') diff --git a/osdep/io.c b/osdep/io.c new file mode 100644 index 0000000000..88433184f4 --- /dev/null +++ b/osdep/io.c @@ -0,0 +1,185 @@ +/* + * unicode/utf-8 I/O helpers and wrappers for Windows + * + * This file is part of mplayer2. + * Contains parts based on libav code (http://libav.org). + * + * mplayer2 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mplayer2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with mplayer2. If not, see . + */ + +#ifdef _WIN32 + +#include +#include +#include +#include + +#include "osdep/io.h" +#include "talloc.h" + +//copied and modified from libav +//http://git.libav.org/?p=libav.git;a=blob;f=libavformat/os_support.c;h=a0fcd6c9ba2be4b0dbcc476f6c53587345cc1152;hb=HEADl30 + +wchar_t *mp_from_utf8(void *talloc_ctx, const char *s) +{ + int count = MultiByteToWideChar(CP_UTF8, 0, s, -1, NULL, 0); + if (count <= 0) + abort(); + wchar_t *ret = talloc_array(talloc_ctx, wchar_t, count); + MultiByteToWideChar(CP_UTF8, 0, s, -1, ret, count); + return ret; +} + +char *mp_to_utf8(void *talloc_ctx, const wchar_t *s) +{ + int count = WideCharToMultiByte(CP_UTF8, 0, s, -1, NULL, 0, NULL, NULL); + if (count <= 0) + abort(); + char *ret = talloc_array(talloc_ctx, char, count); + WideCharToMultiByte(CP_UTF8, 0, s, -1, ret, count, NULL, NULL); + return ret; +} + +#endif // _WIN32 + +#ifdef __MINGW32__ + +#include +#include + +//http://git.libav.org/?p=libav.git;a=blob;f=cmdutils.c;h=ade3f10ce2fc030e32e375a85fbd06c26d43a433#l161 + +static char** win32_argv_utf8; +static int win32_argc; + +void mp_get_converted_argv(int *argc, char ***argv) +{ + if (!win32_argv_utf8) { + win32_argc = 0; + wchar_t **argv_w = CommandLineToArgvW(GetCommandLineW(), &win32_argc); + if (win32_argc <= 0 || !argv_w) + return; + + win32_argv_utf8 = talloc_zero_array(NULL, char*, win32_argc + 1); + + for (int i = 0; i < win32_argc; i++) { + win32_argv_utf8[i] = mp_to_utf8(NULL, argv_w[i]); + } + + LocalFree(argv_w); + } + + *argc = win32_argc; + *argv = win32_argv_utf8; +} + +int mp_stat(const char *path, struct stat *buf) +{ + wchar_t *wpath = mp_from_utf8(NULL, path); + int res = _wstat64(wpath, buf); + talloc_free(wpath); + return res; +} + + +int mp_open(const char *filename, int oflag, ...) +{ + int mode = 0; + if (oflag & _O_CREAT) { + va_list va; + va_start(va, oflag); + mode = va_arg(va, int); + va_end(va); + } + wchar_t *wpath = mp_from_utf8(NULL, filename); + int res = _wopen(wpath, oflag, mode); + talloc_free(wpath); + return res; +} + +int mp_creat(const char *filename, int mode) +{ + return open(filename, O_CREAT|O_WRONLY|O_TRUNC, mode); +} + +FILE *mp_fopen(const char *filename, const char *mode) +{ + wchar_t *wpath = mp_from_utf8(NULL, filename); + wchar_t *wmode = mp_from_utf8(wpath, mode); + FILE *res = _wfopen(wpath, wmode); + talloc_free(wpath); + return res; +} + +struct mp_dir { + DIR crap; // must be first member + _WDIR *wdir; + union { + struct dirent dirent; + // dirent has space only for FILENAME_MAX bytes. _wdirent has space for + // FILENAME_MAX wchar_t, which might end up bigger as UTF-8 in some + // cases. Guarantee we can always hold _wdirent.d_name converted to + // UTF-8 (see MP_PATH_MAX). + // This works because dirent.d_name is the last member of dirent. + char space[MP_PATH_MAX]; + }; +}; + +DIR* mp_opendir(const char *path) +{ + wchar_t *wpath = mp_from_utf8(NULL, path); + _WDIR *wdir = _wopendir(wpath); + talloc_free(wpath); + if (!wdir) + return NULL; + struct mp_dir *mpdir = talloc(NULL, struct mp_dir); + // DIR is supposed to be opaque, but unfortunately the MinGW headers still + // define it. Make sure nobody tries to use it. + memset(&mpdir->crap, 0xCD, sizeof(mpdir->crap)); + mpdir->wdir = wdir; + return (DIR*)mpdir; +} + +struct dirent* mp_readdir(DIR *dir) +{ + struct mp_dir *mpdir = (struct mp_dir*)dir; + struct _wdirent *wdirent = _wreaddir(mpdir->wdir); + if (!wdirent) + return NULL; + size_t buffersize = sizeof(mpdir->space) - offsetof(struct dirent, d_name); + WideCharToMultiByte(CP_UTF8, 0, wdirent->d_name, -1, mpdir->dirent.d_name, + buffersize, NULL, NULL); + mpdir->dirent.d_ino = 0; + mpdir->dirent.d_reclen = 0; + mpdir->dirent.d_namlen = strlen(mpdir->dirent.d_name); + return &mpdir->dirent; +} + +int mp_closedir(DIR *dir) +{ + struct mp_dir *mpdir = (struct mp_dir*)dir; + int res = _wclosedir(mpdir->wdir); + talloc_free(mpdir); + return res; +} + +int mp_mkdir(const char *path, int mode) +{ + wchar_t *wpath = mp_from_utf8(NULL, path); + int res = _wmkdir(wpath); + talloc_free(wpath); + return res; +} + +#endif // __MINGW32__ diff --git a/osdep/io.h b/osdep/io.h new file mode 100644 index 0000000000..514030afca --- /dev/null +++ b/osdep/io.h @@ -0,0 +1,76 @@ +/* + * unicode/utf-8 I/O helpers and wrappers for Windows + * + * This file is part of mplayer2. + * + * mplayer2 is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * mplayer2 is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with mplayer2. If not, see . + */ + +#ifndef MPLAYER_OSDEP_IO +#define MPLAYER_OSDEP_IO + +#include + +#ifdef _WIN32 +#include +wchar_t *mp_from_utf8(void *talloc_ctx, const char *s); +char *mp_to_utf8(void *talloc_ctx, const wchar_t *s); +#endif + +#ifdef __MINGW32__ + +#include +#include +#include +#include + +// Windows' MAX_PATH/PATH_MAX/FILENAME_MAX is fixed to 260, but this limit +// applies to unicode paths encoded with wchar_t (2 bytes on Windows). The UTF-8 +// version could end up bigger in memory. In the worst case each wchar_t is +// encoded to 3 bytes in UTF-8, so in the worst case we have: +// wcslen(wpath) <= strlen(utf8path) * 3 +// Thus we need MP_PATH_MAX as the UTF-8/char version of PATH_MAX. +#define MP_PATH_MAX (FILENAME_MAX * 3) + +void mp_get_converted_argv(int *argc, char ***argv); + +int mp_stat(const char *path, struct stat *buf); +int mp_open(const char *filename, int oflag, ...); +int mp_creat(const char *filename, int mode); +FILE *mp_fopen(const char *filename, const char *mode); +DIR *mp_opendir(const char *path); +struct dirent *mp_readdir(DIR *dir); +int mp_closedir(DIR *dir); +int mp_mkdir(const char *path, int mode); + +// NOTE: Stat is not overridden with mp_stat, because MinGW-w64 defines it as +// macro. + +#define open(...) mp_open(__VA_ARGS__) +#define creat(...) mp_creat(__VA_ARGS__) +#define fopen(...) mp_fopen(__VA_ARGS__) +#define opendir(...) mp_opendir(__VA_ARGS__) +#define readdir(...) mp_readdir(__VA_ARGS__) +#define closedir(...) mp_closedir(__VA_ARGS__) +#define mkdir(...) mp_mkdir(__VA_ARGS__) + +#else /* __MINGW32__ */ + +#define MP_PATH_MAX PATH_MAX + +#define mp_stat(...) stat(__VA_ARGS__) + +#endif /* __MINGW32__ */ + +#endif -- cgit v1.2.3 From f891939b4db79bce39c5f257771557904da4d535 Mon Sep 17 00:00:00 2001 From: Martin Herkt Date: Sat, 22 Oct 2011 16:24:16 +0200 Subject: windows: terminal: unicode, --msgcolor, size change Make mp_msg() support unicode output, --msgcolor and variable screen sizes. Patch reintegrated by wm4. --- osdep/getch2-win.c | 6 ++++++ osdep/io.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ osdep/io.h | 2 ++ 3 files changed, 66 insertions(+) (limited to 'osdep') diff --git a/osdep/getch2-win.c b/osdep/getch2-win.c index 3e6eeff086..326cf1a7d0 100644 --- a/osdep/getch2-win.c +++ b/osdep/getch2-win.c @@ -55,6 +55,12 @@ int screen_height=24; char * erase_to_end_of_line = NULL; void get_screen_size(void){ + CONSOLE_SCREEN_BUFFER_INFO cinfo; + if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cinfo)) + { + screen_width = cinfo.dwMaximumWindowSize.X; + screen_height = cinfo.dwMaximumWindowSize.Y; + } } static HANDLE in; diff --git a/osdep/io.c b/osdep/io.c index 88433184f4..e3e750e30b 100644 --- a/osdep/io.c +++ b/osdep/io.c @@ -92,6 +92,64 @@ int mp_stat(const char *path, struct stat *buf) return res; } +int mp_fprintf(FILE *stream, const char *format, ...) +{ + va_list args; + int done = 0; + + va_start(args, format); + + if (stream == stdout || stream == stderr) + { + HANDLE *wstream = GetStdHandle(stream == stdout ? + STD_OUTPUT_HANDLE : STD_ERROR_HANDLE); + if (wstream != INVALID_HANDLE_VALUE) + { + // figure out whether we're writing to a console + unsigned int filetype = GetFileType(wstream); + if (!((filetype == FILE_TYPE_UNKNOWN) && + (GetLastError() != ERROR_SUCCESS))) + { + int isConsole; + filetype &= ~(FILE_TYPE_REMOTE); + if (filetype == FILE_TYPE_CHAR) + { + DWORD ConsoleMode; + int ret = GetConsoleMode(wstream, &ConsoleMode); + if (!ret && (GetLastError() == ERROR_INVALID_HANDLE)) + isConsole = 0; + else + isConsole = 1; + } + else + isConsole = 0; + + if (isConsole) + { + int nchars = vsnprintf(NULL, 0, format, args) + 1; + char *buf = talloc_array(NULL, char, nchars); + if (buf) + { + vsnprintf(buf, nchars, format, args); + wchar_t *out = mp_from_utf8(NULL, buf); + size_t nchars = wcslen(out); + talloc_free(buf); + done = WriteConsoleW(wstream, out, nchars, NULL, NULL); + talloc_free(out); + } + } + else + done = vfprintf(stream, format, args); + } + } + } + else + done = vfprintf(stream, format, args); + + va_end(args); + + return done; +} int mp_open(const char *filename, int oflag, ...) { diff --git a/osdep/io.h b/osdep/io.h index 514030afca..462a84917b 100644 --- a/osdep/io.h +++ b/osdep/io.h @@ -46,6 +46,7 @@ char *mp_to_utf8(void *talloc_ctx, const wchar_t *s); void mp_get_converted_argv(int *argc, char ***argv); int mp_stat(const char *path, struct stat *buf); +int mp_fprintf(FILE *stream, const char *format, ...); int mp_open(const char *filename, int oflag, ...); int mp_creat(const char *filename, int mode); FILE *mp_fopen(const char *filename, const char *mode); @@ -57,6 +58,7 @@ int mp_mkdir(const char *path, int mode); // NOTE: Stat is not overridden with mp_stat, because MinGW-w64 defines it as // macro. +#define fprintf(...) mp_fprintf(__VA_ARGS__) #define open(...) mp_open(__VA_ARGS__) #define creat(...) mp_creat(__VA_ARGS__) #define fopen(...) mp_fopen(__VA_ARGS__) -- cgit v1.2.3