Windows build!

This commit is contained in:
Scott Duensing 2019-12-29 17:47:16 -06:00
parent 0a2ad6e09e
commit 9b1505c5f1
18 changed files with 705 additions and 92 deletions

2
.gitignore vendored
View file

@ -32,3 +32,5 @@ thirdparty-build/
singe/extensions.h singe/extensions.h
videotest/*.singe videotest/*.singe
games/ games/
build/
singe/source.inc.sh

77
singe/buildRelease.sh Executable file
View file

@ -0,0 +1,77 @@
#!/bin/bash -e
#
# Singe 2
# Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
#
# This program 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.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
source source.inc.sh
function doBuild() {
local TARGET=$1
local OSNAME=$2
local OSARCH=$3
local EXT=$4
local SOURCE=
local I=
local OFILES=""
local O=
pushd "${SOURCE_DIR}/.."
mkdir -p build/${OSNAME}/${OSARCH}
cd build
if [[ -d temp ]]; then
rm -rf temp
fi
mkdir -p temp
cd temp
for I in ${SOURCES}; do
if [[ ${I:0:1} == "/" ]]; then
SOURCE="${I}"
else
SOURCE="${SOURCE_DIR}/${I}"
fi
O=`basename ${SOURCE}`
O=${O%.*}.o
OFILES="${OFILES} ${O}"
echo "Compiling ${SOURCE}..."
${CROSS}-gcc ${QMAKE_CFLAGS} ${EXTRA_CFLAGS} -c "${SOURCE}" -o ${O}
done
TARGET="${SOURCE_DIR}/../build/${OSNAME}/${OSARCH}/${TARGET}${EXT}"
echo "Linking ${TARGET}..."
${CROSS}-g++ -o "${TARGET}" ${OFILES} "-L${SOURCE_DIR}/../thirdparty-build/${OSNAME}/${OSARCH}/installed/lib" ${EXTRA_LD_FLAGS}
echo "Compressing ${TARGET}..."
#${CROSS}-strip "${TARGET}"
#upx -9 "${TARGET}"
popd
}
CROSS="x86_64-linux-gnu"
EXTRA_CFLAGS=""
EXTRA_LD_FLAGS="-l:everything.a -lpthread -lXv -lX11 -lXext -lm -ldl -lrt"
doBuild Singe-Linux-x86_64 linux 64
CROSS="x86_64-w64-mingw32"
EXTRA_CFLAGS=""
EXTRA_LD_FLAGS="-mwindows -static -lmingw32 -l:everything.a -lm -lbcrypt -ldinput8 -ldxguid -ldxerr8 -luser32 -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lshell32 -lsetupapi -lversion -luuid -Dmain=SDL_main"
doBuild Singe-Windows-x86_64 mingw 64 .exe

View file

@ -1,7 +1,7 @@
/* /*
* *
* Singe 2 * Singe 2
* Copyright (C) 2019 Scott Duensing <scott@kangaroopunch.com> * Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License

View file

@ -1,7 +1,7 @@
/* /*
* *
* Singe 2 * Singe 2
* Copyright (C) 2019 Scott Duensing <scott@kangaroopunch.com> * Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -62,6 +62,8 @@ void showUsage(char *name, char *message);
__attribute__((noreturn)) __attribute__((noreturn))
void showUsage(char *name, char *message) { void showUsage(char *name, char *message) {
int result = 0;
utilSay(" ___ ___ _ _ ___ ___"); utilSay(" ___ ___ _ _ ___ ___");
utilSay("/ __|_ _| \\| |/ __| __| Somewhat Interactive Nostalgic Game Emulator %s", VERSION_STRING); utilSay("/ __|_ _| \\| |/ __| __| Somewhat Interactive Nostalgic Game Emulator %s", VERSION_STRING);
utilSay("\\__ \\| || .` | (_ | _| Copyright (c) 2006-%s Scott C. Duensing", COPYRIGHT_END_YEAR); utilSay("\\__ \\| || .` | (_ | _| Copyright (c) 2006-%s Scott C. Duensing", COPYRIGHT_END_YEAR);
@ -91,9 +93,12 @@ void showUsage(char *name, char *message) {
if (message) { if (message) {
utilSay("Error: %s", message); utilSay("Error: %s", message);
utilSay(""); utilSay("");
exit(1); result = 1;
} }
exit(0); #ifdef _WIN32
getchar();
#endif
exit(result);
} }
@ -163,6 +168,9 @@ int main(int argc, char *argv[]) {
{ { 0, 0 }, { 0, 0 } } { { 0, 0 }, { 0, 0 } }
}; };
// For that dumb OS
utilRedirectConsole();
// Parse command line // Parse command line
while (true) { while (true) {
optionIndex = 0; optionIndex = 0;
@ -441,7 +449,7 @@ int main(int argc, char *argv[]) {
if ((_confXResolution > mode.w) || (_confYResolution > mode.h)) showUsage(argv[0], "Specified resolution is larger than the display."); if ((_confXResolution > mode.w) || (_confYResolution > mode.h)) showUsage(argv[0], "Specified resolution is larger than the display.");
// Init SDL_mixer ***FIX*** // Init SDL_mixer ***FIX***
flags = /* MIX_INIT_FLAC | */ MIX_INIT_MOD | MIX_INIT_MP3 | MIX_INIT_OGG | MIX_INIT_MID | MIX_INIT_OPUS; flags = /* MIX_INIT_FLAC | */ MIX_INIT_MOD | /* MIX_INIT_MP3 | */ MIX_INIT_OGG | MIX_INIT_MID | MIX_INIT_OPUS;
err = Mix_Init(flags); err = Mix_Init(flags);
if (err != flags) utilDie("%s", Mix_GetError()); if (err != flags) utilDie("%s", Mix_GetError());
@ -500,5 +508,9 @@ int main(int argc, char *argv[]) {
if (_confScriptFile) free(_confScriptFile); if (_confScriptFile) free(_confScriptFile);
utilTraceEnd(); utilTraceEnd();
#ifdef _WIN32
getchar();
#endif
return 0; return 0;
} }

View file

@ -2,7 +2,7 @@
# #
# Singe 2 # Singe 2
# Copyright (C) 2019 Scott Duensing <scott@kangaroopunch.com> # Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@ -19,8 +19,9 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# #
SOURCE=$1 SOURCEDIR=$1
TARGET=$2 DESTDIR=$2
TARGET=$3
strip "${TARGET}/singe" strip "${DESTDIR}/${TARGET}"
upx -9 "${TARGET}/singe" upx -9 "${DESTDIR}/${TARGET}"

View file

@ -2,7 +2,7 @@
# #
# Singe 2 # Singe 2
# Copyright (C) 2019 Scott Duensing <scott@kangaroopunch.com> # Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@ -191,7 +191,7 @@ function outputLicense() {
/* /*
* *
* Singe 2 * Singe 2
* Copyright (C) 2019 Scott Duensing <scott@kangaroopunch.com> * Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -340,3 +340,42 @@ MODPLUG_CFLAGS="-I${G_INSTALLED}/include -DMODPLUG_STATIC" \
# === SDL2_ttf === # === SDL2_ttf ===
MORE_CFLAGS="-I${G_INSTALLED}/include/SDL2" \ MORE_CFLAGS="-I${G_INSTALLED}/include/SDL2" \
autoBuild libSDL2_ttf.a SDL2_ttf "--with-ft-prefix=\"${G_INSTALLED}\" --with-sdl-prefix=\"${G_INSTALLED}\"" "libSDL2_ttf.la install-libLTLIBRARIES install-libSDL2_ttfincludeHEADERS" autoBuild libSDL2_ttf.a SDL2_ttf "--with-ft-prefix=\"${G_INSTALLED}\" --with-sdl-prefix=\"${G_INSTALLED}\"" "libSDL2_ttf.la install-libLTLIBRARIES install-libSDL2_ttfincludeHEADERS"
# === Combine all dependencies into one big mess ===
if [[ ! -e "${G_INSTALLED}/lib/everything.a" ]]; then
pushd "${G_INSTALLED}/lib"
${G_CROSS}-ar -M <<-LIBS
CREATE everything.a
ADDLIB libSDL2main.a
ADDLIB libSDL2.a
ADDLIB libSDL2_image.a
ADDLIB libpng16.a
ADDLIB libwebp.a
ADDLIB libjpeg.a
ADDLIB libSDL2_mixer.a
ADDLIB libFLAC.a
ADDLIB libmodplug.a
ADDLIB libmpg123.a
ADDLIB libvorbisfile.a
ADDLIB libvorbis.a
ADDLIB libogg.a
ADDLIB libopusfile.a
ADDLIB libopus.a
ADDLIB libSDL2_ttf.a
ADDLIB libfreetype.a
ADDLIB libharfbuzz.a
ADDLIB liblua.a
ADDLIB libffms2.a
ADDLIB libavformat.a
ADDLIB libavcodec.a
ADDLIB libswscale.a
ADDLIB libavutil.a
ADDLIB libswresample.a
ADDLIB libz.a
ADDLIB liblzma.a
ADDLIB libbz2.a
SAVE
END
LIBS
popd
fi

View file

@ -1,7 +1,7 @@
/* /*
* *
* Singe 2 * Singe 2
* Copyright (C) 2019 Scott Duensing <scott@kangaroopunch.com> * Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -187,7 +187,6 @@ static SpriteT *_spriteList = NULL;
static SoundT *_soundList = NULL; static SoundT *_soundList = NULL;
static FontT *_fontList = NULL; static FontT *_fontList = NULL;
static FontT *_fontCurrent = NULL; static FontT *_fontCurrent = NULL;
static void *_pixelBuffer = NULL;
static int _keyDefs[SWITCH_COUNT][2] = { static int _keyDefs[SWITCH_COUNT][2] = {

View file

@ -1,7 +1,7 @@
/* /*
* *
* Singe 2 * Singe 2
* Copyright (C) 2019 Scott Duensing <scott@kangaroopunch.com> * Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License

View file

@ -1,6 +1,6 @@
# #
# Singe 2 # Singe 2
# Copyright (C) 2019 Scott Duensing <scott@kangaroopunch.com> # Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
# #
# This program is free software; you can redistribute it and/or # This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License # modify it under the terms of the GNU General Public License
@ -17,53 +17,36 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# #
TARGET = singeEmu
# We're just a boring old C app # We're just a boring old C app
TEMPLATE = app TEMPLATE = app
CONFIG += console CONFIG += console
CONFIG -= app_bundle CONFIG -= app_bundle
CONFIG -= qt CONFIG -= qt
# Keep binaries to themselves # Target Settings
DESTDIR = $$OUT_PWD/build
# Make Visual C shut up about stupidness TARGET = singeEmu
win32 { CONFIG += platformLinux
DEFINES *= \
_CRT_SECURE_NO_WARNINGS \
_CRT_NONSTDC_NO_DEPRECATE
MSVC_VER = $$(VisualStudioVersion)
if(equals(MSVC_VER, 14.0)|greaterThan(MSVC_VER, 14.0)) {
message("Timespec is defined")
DEFINES *= HAVE_STRUCT_TIMESPEC
}
}
# Determine Bitness - This is just broken
win32 {
contains(QMAKE_HOST.arch, x86_64) {
CONFIG *= bits64
} else {
CONFIG *= bits32
}
} else {
*-64 | *_64 {
CONFIG *= bits64
} else {
CONFIG *= bits32
}
}
BITNESS="64"
bits32:BITNESS="32"
# HACK HACK HACK due to above
BITNESS="64"
CONFIG -= bits32
CONFIG += bits64 CONFIG += bits64
# Keep binaries to themselves
DESTDIR = $$OUT_PWD/build
# === Third Party Builds === # === Third Party Builds ===
BUILDTHIRDARGS = \"$$PWD/thirdparty\" \"$$OUT_PWD/../thirdparty-build\" $$BITNESS bits64 {
BITNESS="64"
} else {
BITNESS="32"
}
platformLinux {
PLATFORM="linux"
} else {
PLATFORM="mingw"
}
BUILDTHIRDARGS = \"$$PWD/thirdparty\" \"$$OUT_PWD/../thirdparty-build\" $$BITNESS $$PLATFORM
win32 { win32 {
# Placeholder - doesn't work # Placeholder - doesn't work
BUILDTHIRD.commands = cmd.exe /c $$PWD\\preBuild.bat $$BUILDTHIRDARGS BUILDTHIRD.commands = cmd.exe /c $$PWD\\preBuild.bat $$BUILDTHIRDARGS
@ -94,7 +77,7 @@ MANYMOUSE_SOURCES = \
QMAKE_CFLAGS += \ QMAKE_CFLAGS += \
-isystem $$MANYMOUSE_INCLUDES \ -isystem $$MANYMOUSE_INCLUDES \
-isystem $$PWD/../thirdparty-build/$$BITNESS/installed/include -isystem $$PWD/../thirdparty-build/$$PLATFORM/$$BITNESS/installed/include
HEADERS += \ HEADERS += \
$$MANYMOUSE_HEADERS \ $$MANYMOUSE_HEADERS \
@ -114,34 +97,8 @@ SOURCES += \
main.c main.c
LIBS += \ LIBS += \
-L$$PWD/../thirdparty-build/$$BITNESS/installed/lib \ -L$$PWD/../thirdparty-build/$$PLATFORM/$$BITNESS/installed/lib \
-l:libSDL2.a \ -l:everything.a \
-l:libSDL2_image.a \
-l:libpng16.a \
-l:libwebp.a \
-l:libjpeg.a \
-l:libSDL2_mixer.a \
-l:libFLAC.a \
-l:libmodplug.a \
-l:libmpg123.a \
-l:libvorbisfile.a \
-l:libvorbis.a \
-l:libogg.a \
-l:libopusfile.a \
-l:libopus.a \
-l:libSDL2_ttf.a \
-l:libfreetype.a \
-l:libharfbuzz.a \
-l:liblua.a \
-l:libffms2.a \
-l:libavformat.a \
-l:libavcodec.a \
-l:libswscale.a \
-l:libavutil.a \
-l:libswresample.a \
-l:libz.a \
-l:liblzma.a \
-l:libbz2.a \
-lpthread \ -lpthread \
-lXv \ -lXv \
-lX11 \ -lX11 \
@ -152,7 +109,16 @@ LIBS += \
OTHER_FILES += \ OTHER_FILES += \
preBuild.sh \ preBuild.sh \
postLink.sh postLink.sh \
buildRelease.sh
FILEINFO = "SOURCES=\"$$SOURCES\"" \
"HEADERS=\"$$HEADERS\"" \
"LINUX_LIBS=\"$$LIBS\"" \
"SOURCE_DIR=\"$$PWD\"" \
"QMAKE_CFLAGS=\"$$QMAKE_CFLAGS\""
write_file("source.inc.sh", FILEINFO)
# Strip & UPX the final result # Strip & UPX the final result
#linux:QMAKE_POST_LINK += bash $$PWD/postLink.sh "$$PWD" "$$DESTDIR" #linux:QMAKE_POST_LINK += bash $$PWD/postLink.sh "$$PWD" "$$DESTDIR" "$$TARGET"

View file

@ -667,9 +667,9 @@ distclean-generic:
maintainer-clean-generic: maintainer-clean-generic:
@echo "This command is intended for maintainers to use" @echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild." @echo "it deletes files that may require special tools to rebuild."
@FLaC__HAS_DOXYGEN_FALSE@uninstall-local:
@FLaC__HAS_DOXYGEN_FALSE@distclean-local:
@FLaC__HAS_DOXYGEN_FALSE@install-data-local: @FLaC__HAS_DOXYGEN_FALSE@install-data-local:
@FLaC__HAS_DOXYGEN_FALSE@distclean-local:
@FLaC__HAS_DOXYGEN_FALSE@uninstall-local:
clean: clean-recursive clean: clean-recursive
clean-am: clean-generic clean-libtool mostlyclean-am clean-am: clean-generic clean-libtool mostlyclean-am

View file

@ -394,9 +394,9 @@ distclean-generic:
maintainer-clean-generic: maintainer-clean-generic:
@echo "This command is intended for maintainers to use" @echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild." @echo "it deletes files that may require special tools to rebuild."
@HAVE_DOXYGEN_FALSE@clean-local:
@HAVE_DOXYGEN_FALSE@uninstall-local: @HAVE_DOXYGEN_FALSE@uninstall-local:
@HAVE_DOXYGEN_FALSE@install-data-local: @HAVE_DOXYGEN_FALSE@install-data-local:
@HAVE_DOXYGEN_FALSE@clean-local:
clean: clean-am clean: clean-am
clean-am: clean-generic clean-libtool clean-local mostlyclean-am clean-am: clean-generic clean-libtool clean-local mostlyclean-am

View file

@ -1018,9 +1018,9 @@ distclean-generic:
maintainer-clean-generic: maintainer-clean-generic:
@echo "This command is intended for maintainers to use" @echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild." @echo "it deletes files that may require special tools to rebuild."
@HAVE_DOXYGEN_FALSE@install-data-local:
@HAVE_DOXYGEN_FALSE@uninstall-local:
@HAVE_DOXYGEN_FALSE@clean-local: @HAVE_DOXYGEN_FALSE@clean-local:
@HAVE_DOXYGEN_FALSE@uninstall-local:
@HAVE_DOXYGEN_FALSE@install-data-local:
clean: clean-am clean: clean-am
clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \ clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \

View file

@ -65,23 +65,31 @@
#endif #endif
// And now for some symbol hide-and-seek... // And now for some symbol hide-and-seek...
/*
#if defined(_WIN32) && !defined(FFMS_STATIC) // MSVC #if defined(_WIN32) && !defined(FFMS_STATIC) // MSVC
# if defined(FFMS_EXPORTS) // building the FFMS2 library itself, with visible API symbols # if defined(FFMS_EXPORTS) // building the FFMS2 library itself, with visible API symbols
# define FFMS_API(ret) FFMS_EXTERN_C __declspec(dllexport) ret FFMS_CC # define FFMS_API(ret) FFMS_EXTERN_C __declspec(dllexport) ret FFMS_CC
# define FFMS_DEPRECATED_API(ret) FFMS_EXTERN_C FFMS_DEPRECATED __declspec(dllexport) ret FFMS_CC # define FFMS_DEPRECATED_API(ret) FFMS_EXTERN_C FFMS_DEPRECATED __declspec(dllexport) ret FFMS_CC
#error Boom 1
# else // building something that depends on FFMS2 # else // building something that depends on FFMS2
# define FFMS_API(ret) FFMS_EXTERN_C __declspec(dllimport) ret FFMS_CC # define FFMS_API(ret) FFMS_EXTERN_C __declspec(dllimport) ret FFMS_CC
# define FFMS_DEPRECATED_API(ret) FFMS_EXTERN_C FFMS_DEPRECATED __declspec(dllimport) ret FFMS_CC # define FFMS_DEPRECATED_API(ret) FFMS_EXTERN_C FFMS_DEPRECATED __declspec(dllimport) ret FFMS_CC
#error Boom 2
# endif // defined(FFMS_EXPORTS) # endif // defined(FFMS_EXPORTS)
// GCC 4 or later: export API symbols only. Some GCC 3.x versions support the visibility attribute too, // GCC 4 or later: export API symbols only. Some GCC 3.x versions support the visibility attribute too,
// but we don't really care enough about that to add compatibility defines for it. // but we don't really care enough about that to add compatibility defines for it.
#elif defined(__GNUC__) && __GNUC__ >= 4 #elif defined(__GNUC__) && __GNUC__ >= 4
*/
# define FFMS_API(ret) FFMS_EXTERN_C __attribute__((visibility("default"))) ret FFMS_CC # define FFMS_API(ret) FFMS_EXTERN_C __attribute__((visibility("default"))) ret FFMS_CC
# define FFMS_DEPRECATED_API(ret) FFMS_EXTERN_C FFMS_DEPRECATED __attribute__((visibility("default"))) ret FFMS_CC # define FFMS_DEPRECATED_API(ret) FFMS_EXTERN_C FFMS_DEPRECATED __attribute__((visibility("default"))) ret FFMS_CC
/*
#error Boom 3
#else // fallback for everything else #else // fallback for everything else
# define FFMS_API(ret) FFMS_EXTERN_C ret FFMS_CC # define FFMS_API(ret) FFMS_EXTERN_C ret FFMS_CC
# define FFMS_DEPRECATED_API(ret) FFMS_EXTERN_C FFMS_DEPRECATED ret FFMS_CC # define FFMS_DEPRECATED_API(ret) FFMS_EXTERN_C FFMS_DEPRECATED ret FFMS_CC
#error Boom 4
#endif // defined(_MSC_VER) #endif // defined(_MSC_VER)
*/
// we now return you to your regularly scheduled programming. // we now return you to your regularly scheduled programming.

View file

@ -0,0 +1,455 @@
// Copyright (c) 2007-2018 Fredrik Mellbin
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#ifndef FFMS_H
#define FFMS_H
// Version format: major - minor - micro - bump
#define FFMS_VERSION ((2 << 24) | (31 << 16) | (0 << 8) | 0)
#include <stdint.h>
#include <stddef.h>
/********
* The following preprocessor voodoo ensures that all API symbols are exported
* as intended on all supported platforms, that non-API symbols are hidden (where possible),
* and that the correct calling convention and extern declarations are used.
* The end result should be that linking to FFMS2 Just Works.
********/
// Convenience for C++ users.
#if defined(__cplusplus)
# define FFMS_EXTERN_C extern "C"
#else
# define FFMS_EXTERN_C
#endif
// On win32, we need to ensure we use stdcall with all compilers.
#if defined(_WIN32) && !defined(_WIN64)
# define FFMS_CC __stdcall
#else
# define FFMS_CC
#endif
// compiler-specific deprecation attributes
#ifndef FFMS_EXPORTS
# if defined(__GNUC__) && (__GNUC__ >= 4)
# define FFMS_DEPRECATED __attribute__((deprecated))
# elif defined(_MSC_VER)
# define FFMS_DEPRECATED __declspec(deprecated)
# endif
#endif
#ifndef FFMS_DEPRECATED
// Define as empty if the compiler doesn't support deprecation attributes or
// if we're building FFMS2 itself
# define FFMS_DEPRECATED
#endif
// And now for some symbol hide-and-seek...
#if defined(_WIN32) && !defined(FFMS_STATIC) // MSVC
# if defined(FFMS_EXPORTS) // building the FFMS2 library itself, with visible API symbols
# define FFMS_API(ret) FFMS_EXTERN_C __declspec(dllexport) ret FFMS_CC
# define FFMS_DEPRECATED_API(ret) FFMS_EXTERN_C FFMS_DEPRECATED __declspec(dllexport) ret FFMS_CC
# else // building something that depends on FFMS2
# define FFMS_API(ret) FFMS_EXTERN_C __declspec(dllimport) ret FFMS_CC
# define FFMS_DEPRECATED_API(ret) FFMS_EXTERN_C FFMS_DEPRECATED __declspec(dllimport) ret FFMS_CC
# endif // defined(FFMS_EXPORTS)
// GCC 4 or later: export API symbols only. Some GCC 3.x versions support the visibility attribute too,
// but we don't really care enough about that to add compatibility defines for it.
#elif defined(__GNUC__) && __GNUC__ >= 4
# define FFMS_API(ret) FFMS_EXTERN_C __attribute__((visibility("default"))) ret FFMS_CC
# define FFMS_DEPRECATED_API(ret) FFMS_EXTERN_C FFMS_DEPRECATED __attribute__((visibility("default"))) ret FFMS_CC
#else // fallback for everything else
# define FFMS_API(ret) FFMS_EXTERN_C ret FFMS_CC
# define FFMS_DEPRECATED_API(ret) FFMS_EXTERN_C FFMS_DEPRECATED ret FFMS_CC
#endif // defined(_MSC_VER)
// we now return you to your regularly scheduled programming.
typedef struct FFMS_ErrorInfo {
int ErrorType;
int SubType;
int BufferSize;
char *Buffer;
} FFMS_ErrorInfo;
typedef struct FFMS_VideoSource FFMS_VideoSource;
typedef struct FFMS_AudioSource FFMS_AudioSource;
typedef struct FFMS_Indexer FFMS_Indexer;
typedef struct FFMS_Index FFMS_Index;
typedef struct FFMS_Track FFMS_Track;
typedef enum FFMS_Errors {
// No error
FFMS_ERROR_SUCCESS = 0,
// Main types - where the error occurred
FFMS_ERROR_INDEX = 1, // index file handling
FFMS_ERROR_INDEXING, // indexing
FFMS_ERROR_POSTPROCESSING, // video postprocessing (libpostproc)
FFMS_ERROR_SCALING, // image scaling (libswscale)
FFMS_ERROR_DECODING, // audio/video decoding
FFMS_ERROR_SEEKING, // seeking
FFMS_ERROR_PARSER, // file parsing
FFMS_ERROR_TRACK, // track handling
FFMS_ERROR_WAVE_WRITER, // WAVE64 file writer
FFMS_ERROR_CANCELLED, // operation aborted
FFMS_ERROR_RESAMPLING, // audio resampling (libavresample)
// Subtypes - what caused the error
FFMS_ERROR_UNKNOWN = 20, // unknown error
FFMS_ERROR_UNSUPPORTED, // format or operation is not supported with this binary
FFMS_ERROR_FILE_READ, // cannot read from file
FFMS_ERROR_FILE_WRITE, // cannot write to file
FFMS_ERROR_NO_FILE, // no such file or directory
FFMS_ERROR_VERSION, // wrong version
FFMS_ERROR_ALLOCATION_FAILED, // out of memory
FFMS_ERROR_INVALID_ARGUMENT, // invalid or nonsensical argument
FFMS_ERROR_CODEC, // decoder error
FFMS_ERROR_NOT_AVAILABLE, // requested mode or operation unavailable in this binary
FFMS_ERROR_FILE_MISMATCH, // provided index does not match the file
FFMS_ERROR_USER // problem exists between keyboard and chair
} FFMS_Errors;
typedef enum FFMS_SeekMode {
FFMS_SEEK_LINEAR_NO_RW = -1,
FFMS_SEEK_LINEAR = 0,
FFMS_SEEK_NORMAL = 1,
FFMS_SEEK_UNSAFE = 2,
FFMS_SEEK_AGGRESSIVE = 3
} FFMS_SeekMode;
typedef enum FFMS_IndexErrorHandling {
FFMS_IEH_ABORT = 0,
FFMS_IEH_CLEAR_TRACK = 1,
FFMS_IEH_STOP_TRACK = 2,
FFMS_IEH_IGNORE = 3
} FFMS_IndexErrorHandling;
typedef enum FFMS_TrackType {
FFMS_TYPE_UNKNOWN = -1,
FFMS_TYPE_VIDEO,
FFMS_TYPE_AUDIO,
FFMS_TYPE_DATA,
FFMS_TYPE_SUBTITLE,
FFMS_TYPE_ATTACHMENT
} FFMS_TrackType;
typedef enum FFMS_SampleFormat {
FFMS_FMT_U8 = 0,
FFMS_FMT_S16,
FFMS_FMT_S32,
FFMS_FMT_FLT,
FFMS_FMT_DBL
} FFMS_SampleFormat;
typedef enum FFMS_AudioChannel {
FFMS_CH_FRONT_LEFT = 0x00000001,
FFMS_CH_FRONT_RIGHT = 0x00000002,
FFMS_CH_FRONT_CENTER = 0x00000004,
FFMS_CH_LOW_FREQUENCY = 0x00000008,
FFMS_CH_BACK_LEFT = 0x00000010,
FFMS_CH_BACK_RIGHT = 0x00000020,
FFMS_CH_FRONT_LEFT_OF_CENTER = 0x00000040,
FFMS_CH_FRONT_RIGHT_OF_CENTER = 0x00000080,
FFMS_CH_BACK_CENTER = 0x00000100,
FFMS_CH_SIDE_LEFT = 0x00000200,
FFMS_CH_SIDE_RIGHT = 0x00000400,
FFMS_CH_TOP_CENTER = 0x00000800,
FFMS_CH_TOP_FRONT_LEFT = 0x00001000,
FFMS_CH_TOP_FRONT_CENTER = 0x00002000,
FFMS_CH_TOP_FRONT_RIGHT = 0x00004000,
FFMS_CH_TOP_BACK_LEFT = 0x00008000,
FFMS_CH_TOP_BACK_CENTER = 0x00010000,
FFMS_CH_TOP_BACK_RIGHT = 0x00020000,
FFMS_CH_STEREO_LEFT = 0x20000000,
FFMS_CH_STEREO_RIGHT = 0x40000000
} FFMS_AudioChannel;
typedef enum FFMS_Resizers {
FFMS_RESIZER_FAST_BILINEAR = 0x0001,
FFMS_RESIZER_BILINEAR = 0x0002,
FFMS_RESIZER_BICUBIC = 0x0004,
FFMS_RESIZER_X = 0x0008,
FFMS_RESIZER_POINT = 0x0010,
FFMS_RESIZER_AREA = 0x0020,
FFMS_RESIZER_BICUBLIN = 0x0040,
FFMS_RESIZER_GAUSS = 0x0080,
FFMS_RESIZER_SINC = 0x0100,
FFMS_RESIZER_LANCZOS = 0x0200,
FFMS_RESIZER_SPLINE = 0x0400
} FFMS_Resizers;
typedef enum FFMS_AudioDelayModes {
FFMS_DELAY_NO_SHIFT = -3,
FFMS_DELAY_TIME_ZERO = -2,
FFMS_DELAY_FIRST_VIDEO_TRACK = -1
} FFMS_AudioDelayModes;
typedef enum FFMS_ChromaLocations {
FFMS_LOC_UNSPECIFIED = 0,
FFMS_LOC_LEFT = 1,
FFMS_LOC_CENTER = 2,
FFMS_LOC_TOPLEFT = 3,
FFMS_LOC_TOP = 4,
FFMS_LOC_BOTTOMLEFT = 5,
FFMS_LOC_BOTTOM = 6
} FFMS_ChromaLocations;
typedef enum FFMS_ColorRanges {
FFMS_CR_UNSPECIFIED = 0,
FFMS_CR_MPEG = 1, // 219*2^(n-8), i.e. 16-235 with 8-bit samples
FFMS_CR_JPEG = 2 // 2^n-1, or "fullrange"
} FFMS_ColorRanges;
typedef enum FFMS_Stereo3DType {
FFMS_S3D_TYPE_2D = 0,
FFMS_S3D_TYPE_SIDEBYSIDE,
FFMS_S3D_TYPE_TOPBOTTOM,
FFMS_S3D_TYPE_FRAMESEQUENCE,
FFMS_S3D_TYPE_CHECKERBOARD,
FFMS_S3D_TYPE_SIDEBYSIDE_QUINCUNX,
FFMS_S3D_TYPE_LINES,
FFMS_S3D_TYPE_COLUMNS
} FFMS_Stereo3DType;
typedef enum FFMS_Stereo3DFlags {
FFMS_S3D_FLAGS_INVERT = 1
} FFMS_Stereo3DFlags;
typedef enum FFMS_MixingCoefficientType {
FFMS_MIXING_COEFFICIENT_Q8 = 0,
FFMS_MIXING_COEFFICIENT_Q15 = 1,
FFMS_MIXING_COEFFICIENT_FLT = 2
} FFMS_MixingCoefficientType;
typedef enum FFMS_MatrixEncoding {
FFMS_MATRIX_ENCODING_NONE = 0,
FFMS_MATRIX_ENCODING_DOBLY = 1,
FFMS_MATRIX_ENCODING_PRO_LOGIC_II = 2,
FFMS_MATRIX_ENCODING_PRO_LOGIC_IIX = 3,
FFMS_MATRIX_ENCODING_PRO_LOGIC_IIZ = 4,
FFMS_MATRIX_ENCODING_DOLBY_EX = 5,
FFMS_MATRIX_ENCODING_DOLBY_HEADPHONE = 6
} FFMS_MatrixEncoding;
typedef enum FFMS_ResampleFilterType {
FFMS_RESAMPLE_FILTER_CUBIC = 0,
FFMS_RESAMPLE_FILTER_SINC = 1, /* misnamed as multiple windowsed sinc filters exist, actually called BLACKMAN_NUTTALL */
FFMS_RESAMPLE_FILTER_KAISER = 2
} FFMS_ResampleFilterType;
typedef enum FFMS_AudioDitherMethod {
FFMS_RESAMPLE_DITHER_NONE = 0,
FFMS_RESAMPLE_DITHER_RECTANGULAR = 1,
FFMS_RESAMPLE_DITHER_TRIANGULAR = 2,
FFMS_RESAMPLE_DITHER_TRIANGULAR_HIGHPASS = 3,
FFMS_RESAMPLE_DITHER_TRIANGULAR_NOISESHAPING = 4
} FFMS_AudioDitherMethod;
typedef enum FFMS_LogLevels {
FFMS_LOG_QUIET = -8,
FFMS_LOG_PANIC = 0,
FFMS_LOG_FATAL = 8,
FFMS_LOG_ERROR = 16,
FFMS_LOG_WARNING = 24,
FFMS_LOG_INFO = 32,
FFMS_LOG_VERBOSE = 40,
FFMS_LOG_DEBUG = 48,
FFMS_LOG_TRACE = 56
} FFMS_LogLevels;
typedef struct FFMS_ResampleOptions {
int64_t ChannelLayout;
FFMS_SampleFormat SampleFormat;
int SampleRate;
FFMS_MixingCoefficientType MixingCoefficientType;
double CenterMixLevel;
double SurroundMixLevel;
double LFEMixLevel;
int Normalize;
int ForceResample;
int ResampleFilterSize;
int ResamplePhaseShift;
int LinearInterpolation;
double CutoffFrequencyRatio;
FFMS_MatrixEncoding MatrixedStereoEncoding;
FFMS_ResampleFilterType FilterType;
int KaiserBeta;
FFMS_AudioDitherMethod DitherMethod;
} FFMS_ResampleOptions;
typedef struct FFMS_Frame {
const uint8_t *Data[4];
int Linesize[4];
int EncodedWidth;
int EncodedHeight;
int EncodedPixelFormat;
int ScaledWidth;
int ScaledHeight;
int ConvertedPixelFormat;
int KeyFrame;
int RepeatPict;
int InterlacedFrame;
int TopFieldFirst;
char PictType;
int ColorSpace;
int ColorRange;
/* Introduced in FFMS_VERSION ((2 << 24) | (21 << 16) | (0 << 8) | 0) */
int ColorPrimaries;
int TransferCharateristics;
int ChromaLocation;
/* Introduced in FFMS_VERSION ((2 << 24) | (27 << 16) | (0 << 8) | 0) */
int HasMasteringDisplayPrimaries; /* Non-zero if the 4 fields below are valid */
double MasteringDisplayPrimariesX[3];
double MasteringDisplayPrimariesY[3];
double MasteringDisplayWhitePointX;
double MasteringDisplayWhitePointY;
int HasMasteringDisplayLuminance; /* Non-zero if the 2 fields below are valid */
double MasteringDisplayMinLuminance;
double MasteringDisplayMaxLuminance;
int HasContentLightLevel; /* Non-zero if the 2 fields below are valid */
unsigned int ContentLightLevelMax;
unsigned int ContentLightLevelAverage;
} FFMS_Frame;
typedef struct FFMS_TrackTimeBase {
int64_t Num;
int64_t Den;
} FFMS_TrackTimeBase;
typedef struct FFMS_FrameInfo {
int64_t PTS;
int RepeatPict;
int KeyFrame;
int64_t OriginalPTS;
} FFMS_FrameInfo;
typedef struct FFMS_VideoProperties {
int FPSDenominator;
int FPSNumerator;
int RFFDenominator;
int RFFNumerator;
int NumFrames;
int SARNum;
int SARDen;
int CropTop;
int CropBottom;
int CropLeft;
int CropRight;
int TopFieldFirst;
FFMS_DEPRECATED int ColorSpace; /* Provided in FFMS_Frame */
FFMS_DEPRECATED int ColorRange; /* Provided in FFMS_Frame */
double FirstTime;
double LastTime;
/* Introduced in FFMS_VERSION ((2 << 24) | (24 << 16) | (0 << 8) | 0) */
int Rotation;
int Stereo3DType;
int Stereo3DFlags;
/* Introduced in FFMS_VERSION ((2 << 24) | (30 << 16) | (0 << 8) | 0) */
double LastEndTime;
int HasMasteringDisplayPrimaries; /* Non-zero if the 4 fields below are valid */
double MasteringDisplayPrimariesX[3];
double MasteringDisplayPrimariesY[3];
double MasteringDisplayWhitePointX;
double MasteringDisplayWhitePointY;
int HasMasteringDisplayLuminance; /* Non-zero if the 2 fields below are valid */
double MasteringDisplayMinLuminance;
double MasteringDisplayMaxLuminance;
int HasContentLightLevel; /* Non-zero if the 2 fields below are valid */
unsigned int ContentLightLevelMax;
unsigned int ContentLightLevelAverage;
/* Introduced in FFMS_VERSION ((2 << 24) | (31 << 16) | (0 << 8) | 0) */
int Flip;
} FFMS_VideoProperties;
typedef struct FFMS_AudioProperties {
int SampleFormat;
int SampleRate;
int BitsPerSample;
int Channels;
int64_t ChannelLayout; // should probably be a plain int, none of the constants are >32 bits long
int64_t NumSamples;
double FirstTime;
double LastTime;
/* Introduced in FFMS_VERSION ((2 << 24) | (30 << 16) | (0 << 8) | 0) */
double LastEndTime;
} FFMS_AudioProperties;
typedef int (FFMS_CC *TIndexCallback)(int64_t Current, int64_t Total, void *ICPrivate);
/* Most functions return 0 on success */
/* Functions without error message output can be assumed to never fail in a graceful way */
FFMS_API(void) FFMS_Init(int, int); /* Pass 0 to both arguments, kept to partially preserve abi */
FFMS_API(void) FFMS_Deinit();
FFMS_API(int) FFMS_GetVersion();
FFMS_API(int) FFMS_GetLogLevel();
FFMS_API(void) FFMS_SetLogLevel(int Level);
FFMS_API(FFMS_VideoSource *) FFMS_CreateVideoSource(const char *SourceFile, int Track, FFMS_Index *Index, int Threads, int SeekMode, FFMS_ErrorInfo *ErrorInfo);
FFMS_API(FFMS_AudioSource *) FFMS_CreateAudioSource(const char *SourceFile, int Track, FFMS_Index *Index, int DelayMode, FFMS_ErrorInfo *ErrorInfo);
FFMS_API(void) FFMS_DestroyVideoSource(FFMS_VideoSource *V);
FFMS_API(void) FFMS_DestroyAudioSource(FFMS_AudioSource *A);
FFMS_API(const FFMS_VideoProperties *) FFMS_GetVideoProperties(FFMS_VideoSource *V);
FFMS_API(const FFMS_AudioProperties *) FFMS_GetAudioProperties(FFMS_AudioSource *A);
FFMS_API(const FFMS_Frame *) FFMS_GetFrame(FFMS_VideoSource *V, int n, FFMS_ErrorInfo *ErrorInfo);
FFMS_API(const FFMS_Frame *) FFMS_GetFrameByTime(FFMS_VideoSource *V, double Time, FFMS_ErrorInfo *ErrorInfo);
FFMS_API(int) FFMS_GetAudio(FFMS_AudioSource *A, void *Buf, int64_t Start, int64_t Count, FFMS_ErrorInfo *ErrorInfo);
FFMS_API(int) FFMS_SetOutputFormatV2(FFMS_VideoSource *V, const int *TargetFormats, int Width, int Height, int Resizer, FFMS_ErrorInfo *ErrorInfo); /* Introduced in FFMS_VERSION ((2 << 24) | (15 << 16) | (3 << 8) | 0) */
FFMS_API(void) FFMS_ResetOutputFormatV(FFMS_VideoSource *V);
FFMS_API(int) FFMS_SetInputFormatV(FFMS_VideoSource *V, int ColorSpace, int ColorRange, int Format, FFMS_ErrorInfo *ErrorInfo); /* Introduced in FFMS_VERSION ((2 << 24) | (17 << 16) | (1 << 8) | 0) */
FFMS_API(void) FFMS_ResetInputFormatV(FFMS_VideoSource *V);
FFMS_API(FFMS_ResampleOptions *) FFMS_CreateResampleOptions(FFMS_AudioSource *A); /* Introduced in FFMS_VERSION ((2 << 24) | (15 << 16) | (4 << 8) | 0) */
FFMS_API(int) FFMS_SetOutputFormatA(FFMS_AudioSource *A, const FFMS_ResampleOptions*options, FFMS_ErrorInfo *ErrorInfo); /* Introduced in FFMS_VERSION ((2 << 24) | (15 << 16) | (4 << 8) | 0) */
FFMS_API(void) FFMS_DestroyResampleOptions(FFMS_ResampleOptions *options); /* Introduced in FFMS_VERSION ((2 << 24) | (15 << 16) | (4 << 8) | 0) */
FFMS_API(void) FFMS_DestroyIndex(FFMS_Index *Index);
FFMS_API(int) FFMS_GetFirstTrackOfType(FFMS_Index *Index, int TrackType, FFMS_ErrorInfo *ErrorInfo);
FFMS_API(int) FFMS_GetFirstIndexedTrackOfType(FFMS_Index *Index, int TrackType, FFMS_ErrorInfo *ErrorInfo);
FFMS_API(int) FFMS_GetNumTracks(FFMS_Index *Index);
FFMS_API(int) FFMS_GetNumTracksI(FFMS_Indexer *Indexer);
FFMS_API(int) FFMS_GetTrackType(FFMS_Track *T);
FFMS_API(int) FFMS_GetTrackTypeI(FFMS_Indexer *Indexer, int Track);
FFMS_API(FFMS_IndexErrorHandling) FFMS_GetErrorHandling(FFMS_Index *Index);
FFMS_API(const char *) FFMS_GetCodecNameI(FFMS_Indexer *Indexer, int Track);
FFMS_API(const char *) FFMS_GetFormatNameI(FFMS_Indexer *Indexer);
FFMS_API(int) FFMS_GetNumFrames(FFMS_Track *T);
FFMS_API(const FFMS_FrameInfo *) FFMS_GetFrameInfo(FFMS_Track *T, int Frame);
FFMS_API(FFMS_Track *) FFMS_GetTrackFromIndex(FFMS_Index *Index, int Track);
FFMS_API(FFMS_Track *) FFMS_GetTrackFromVideo(FFMS_VideoSource *V);
FFMS_API(FFMS_Track *) FFMS_GetTrackFromAudio(FFMS_AudioSource *A);
FFMS_API(const FFMS_TrackTimeBase *) FFMS_GetTimeBase(FFMS_Track *T);
FFMS_API(int) FFMS_WriteTimecodes(FFMS_Track *T, const char *TimecodeFile, FFMS_ErrorInfo *ErrorInfo);
FFMS_API(FFMS_Indexer *) FFMS_CreateIndexer(const char *SourceFile, FFMS_ErrorInfo *ErrorInfo);
FFMS_API(void) FFMS_TrackIndexSettings(FFMS_Indexer *Indexer, int Track, int Index, int); /* Pass 0 to last argument, kapt to preserve abi. Introduced in FFMS_VERSION ((2 << 24) | (21 << 16) | (0 << 8) | 0) */
FFMS_API(void) FFMS_TrackTypeIndexSettings(FFMS_Indexer *Indexer, int TrackType, int Index, int); /* Pass 0 to last argument, kapt to preserve abi. Introduced in FFMS_VERSION ((2 << 24) | (21 << 16) | (0 << 8) | 0) */
FFMS_API(void) FFMS_SetProgressCallback(FFMS_Indexer *Indexer, TIndexCallback IC, void *ICPrivate); /* Introduced in FFMS_VERSION ((2 << 24) | (21 << 16) | (0 << 8) | 0) */
FFMS_API(FFMS_Index *) FFMS_DoIndexing2(FFMS_Indexer *Indexer, int ErrorHandling, FFMS_ErrorInfo *ErrorInfo); /* Introduced in FFMS_VERSION ((2 << 24) | (21 << 16) | (0 << 8) | 0) */
FFMS_API(void) FFMS_CancelIndexing(FFMS_Indexer *Indexer);
FFMS_API(FFMS_Index *) FFMS_ReadIndex(const char *IndexFile, FFMS_ErrorInfo *ErrorInfo);
FFMS_API(FFMS_Index *) FFMS_ReadIndexFromBuffer(const uint8_t *Buffer, size_t Size, FFMS_ErrorInfo *ErrorInfo);
FFMS_API(int) FFMS_IndexBelongsToFile(FFMS_Index *Index, const char *SourceFile, FFMS_ErrorInfo *ErrorInfo);
FFMS_API(int) FFMS_WriteIndex(const char *IndexFile, FFMS_Index *Index, FFMS_ErrorInfo *ErrorInfo);
FFMS_API(int) FFMS_WriteIndexToBuffer(uint8_t **BufferPtr, size_t *Size, FFMS_Index *Index, FFMS_ErrorInfo *ErrorInfo);
FFMS_API(void) FFMS_FreeIndexBuffer(uint8_t **BufferPtr);
FFMS_API(int) FFMS_GetPixFmt(const char *Name);
#endif

View file

@ -1,7 +1,7 @@
/* /*
* *
* Singe 2 * Singe 2
* Copyright (C) 2019 Scott Duensing <scott@kangaroopunch.com> * Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -20,6 +20,16 @@
*/ */
#ifdef _WIN32
#include <windows.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
static const int CONSOLE_LINES = 1000;
#endif
#include <stdlib.h> #include <stdlib.h>
#include <dirent.h> #include <dirent.h>
#include <string.h> #include <string.h>
@ -69,6 +79,9 @@ void utilDie(char *fmt, ...) {
va_end(args); va_end(args);
printf("\n"); printf("\n");
fflush(stderr); fflush(stderr);
#ifdef _WIN32
getchar();
#endif
exit(1); exit(1);
} }
@ -136,6 +149,46 @@ bool utilPathExists(char *pathname) {
} }
void utilRedirectConsole(void) {
#ifdef _WIN32
// http://dslweb.nwnexus.com/~ast/dload/guicon.htm
int hConHandle;
intptr_t lStdHandle;
CONSOLE_SCREEN_BUFFER_INFO coninfo;
FILE *fp;
// allocate a console for this app
AllocConsole();
// set the screen buffer to be big enough to let us scroll text
GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &coninfo);
coninfo.dwSize.Y = CONSOLE_LINES;
SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), coninfo.dwSize);
// redirect unbuffered STDOUT to the console
lStdHandle = (intptr_t)GetStdHandle(STD_OUTPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "w");
*stdout = *fp;
setvbuf(stdout, NULL, _IONBF, 0);
// redirect unbuffered STDIN to the console
lStdHandle = (intptr_t)GetStdHandle(STD_INPUT_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "r");
*stdin = *fp;
setvbuf(stdin, NULL, _IONBF, 0);
// redirect unbuffered STDERR to the console
lStdHandle = (intptr_t)GetStdHandle(STD_ERROR_HANDLE);
hConHandle = _open_osfhandle(lStdHandle, _O_TEXT);
fp = _fdopen(hConHandle, "w");
*stderr = *fp;
setvbuf(stderr, NULL, _IONBF, 0);
#endif
}
__attribute__((__format__(__printf__, 1, 0))) __attribute__((__format__(__printf__, 1, 0)))
void utilSay(char *fmt, ...) { void utilSay(char *fmt, ...) {
va_list args; va_list args;

View file

@ -1,7 +1,7 @@
/* /*
* *
* Singe 2 * Singe 2
* Copyright (C) 2019 Scott Duensing <scott@kangaroopunch.com> * Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License
@ -42,6 +42,7 @@ char *utilGetFileExtension(char *filename);
char *utilGetLastPathComponent(char *pathname); char *utilGetLastPathComponent(char *pathname);
char utilGetPathSeparator(void); char utilGetPathSeparator(void);
bool utilPathExists(char *pathname); bool utilPathExists(char *pathname);
void utilRedirectConsole(void);
void utilSay(char *fmt, ...); void utilSay(char *fmt, ...);
void utilTrace(char *fmt, ...); void utilTrace(char *fmt, ...);
void utilTraceEnd(void); void utilTraceEnd(void);

View file

@ -1,7 +1,7 @@
/* /*
* *
* Singe 2 * Singe 2
* Copyright (C) 2019 Scott Duensing <scott@kangaroopunch.com> * Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License

View file

@ -1,7 +1,7 @@
/* /*
* *
* Singe 2 * Singe 2
* Copyright (C) 2019 Scott Duensing <scott@kangaroopunch.com> * Copyright (C) 2006-2020 Scott Duensing <scott@kangaroopunch.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License * modify it under the terms of the GNU General Public License