diff --git a/.travis.yml b/.travis.yml index 1a5ca2e1a..e5d9e6afc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,19 @@ language: cpp sudo: true -dist: trusty +dist: bionic addons: apt: sources: - ubuntu-toolchain-r-test packages: - - libsdl1.2-dev - - libsdl-mixer1.2-dev - - libsdl-image1.2-dev + - libsdl2-dev + - libsdl2-mixer-dev + - libsdl2-image-dev + - libtiff-dev + - libavcodec-dev + - libavformat-dev + - libswscale-dev - byacc - - gtk+-2.0-dev - gcc-5 - g++-5 diff --git a/Dockerfile b/Dockerfile index 13c4dd625..d04928279 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,8 +16,8 @@ RUN useradd -m $USERNAME && \ FROM system as builder RUN apt-get update && apt-get install -y --no-install-recommends \ - libsdl1.2-dev libsdl-mixer1.2-dev libsdl-image1.2-dev byacc libgtk2.0-dev gcc-5 g++-5 \ - automake libtool unzip flex git ca-certificates + libsdl2-dev libsdl2-mixer-dev libsdl2-image-dev libtiff-dev libavcodec-dev libavformat-dev libswscale-dev \ + byacc gcc-5 g++-5 automake libtool unzip flex git ca-certificates ### set default compilers RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 100 && \ @@ -29,31 +29,6 @@ RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 100 && \ c++ --version && \ cpp --version -### build ffmpeg -RUN git clone --depth 1 -b v0.5.2 http://github.com/FFmpeg/FFmpeg/ && \ - cd FFmpeg && \ - ./configure \ - --prefix=/usr/local/ \ - --disable-ffmpeg \ - --disable-ffplay \ - --disable-ffserver && \ - make -j"$(nproc)" && \ - make install - -### ffmpeg built - -### build SDL_ffmpeg -RUN git clone -b v0.9.0 http://github.com/lynxabraxas/SDL_ffmpeg && \ - cd /SDL_ffmpeg/trunk/ && \ - sed -i 's/CFLAGS=-I$INCDIR/CFLAGS="$CFLAGS -I$INCDIR"/' configure && \ - sed -i 's/LDFLAGS=-L$LIBDIR/LDFLAGS="$LDFLAGS -L$LIBDIR"/' configure && \ - LDFLAGS="-lm" \ - ./configure --prefix=/usr/local/ --static=yes && \ - make && \ - make install - -### SDL_ffmpeg built - ENV LD_LIBRARY_PATH "${LD_LIBRARY_PATH}:/usr/local/lib" ## ctp2CD/ copy not done in builder stage such that stages before are compatible with travis docker build @@ -67,12 +42,10 @@ ARG BTYP RUN cd /ctp2 \ && ./autogen.sh \ - && CPPFLAGS="-I/usr/local/include/SDL/" \ - CC=/usr/bin/gcc-5 \ + && CC=/usr/bin/gcc-5 \ CXX=/usr/bin/g++-5 \ CFLAGS="$CFLAGS -w $( [ "${BTYP##*debug*}" ] && echo -O3 || echo -ggdb -rdynamic ) -fuse-ld=gold" \ CXXFLAGS="$CXXFLAGS -fpermissive -w $( [ "${BTYP##*debug*}" ] && echo -O3 || echo -ggdb -rdynamic ) -fuse-ld=gold" \ - LDFLAGS="$LDFLAGS -L/usr/local/lib" \ ./configure --prefix=/opt/ctp2 --bindir=/opt/ctp2/ctp2_program/ctp --enable-silent-rules $( [ "${BTYP##*debug*}" ] || echo --enable-debug ) \ && make -j"$(nproc)" \ && make -j"$(nproc)" install \ @@ -89,15 +62,11 @@ FROM system as install ARG BTYP RUN apt-get update && apt-get install -y --no-install-recommends \ - libsdl1.2debian libsdl-mixer1.2 libsdl-image1.2 libgtk2.0-0 \ + libsdl2-2.0 libsdl2-mixer-2.0 libsdl2-image-2.0 libavcodec57 libavformat57 libswscale4 \ gdb libstdc++-5-dev && \ apt-get clean && \ rm -rf /var/lib/apt/lists/* -## copy libs first since they are less likely to change -COPY --from=builder /usr/local/lib /usr/local/lib -ENV LD_LIBRARY_PATH "${LD_LIBRARY_PATH}:/usr/local/lib" - ## ctp2CD/ copy done in install stage such that stages before are compatible with travis docker build, results in one additional layer in the final DI (incr. DI download size) COPY ctp2CD/ /opt/ctp2/ ## ctp2/ copy has to be after ctp2CD/ to overwrite with newer versions from civctp2 diff --git a/GNUmakefile.am b/GNUmakefile.am index 94073a0b3..5ccbb127e 100644 --- a/GNUmakefile.am +++ b/GNUmakefile.am @@ -13,6 +13,15 @@ bootstrap bootstrap-anet doc local playtest: $(top_srcdir)/Makefile .PHONY: purge bootstrap doc local playtest if DEBUG +all-local: + nm --demangle --defined-only --numeric-sort $(top_srcdir)/ctp2_code/ctp/ctp2 > $(top_srcdir)/ctp2_code/ctp/ctp2linux.map + install-data-hook: nm --demangle --defined-only --numeric-sort $(DESTDIR)$(bindir)/ctp2 > $(DESTDIR)$(bindir)/ctp2linux.map endif + +clean-local: + rm -f $(top_srcdir)/ctp2_code/ctp/ctp2linux.map + +uninstall-local: + rm -f $(DESTDIR)$(bindir)/ctp2linux.map diff --git a/README.md b/README.md index d8ece5434..7b755c881 100644 --- a/README.md +++ b/README.md @@ -18,15 +18,17 @@ Note that the game files are not included in this repo, you can get them from th ![screenshot](screenshot.png "screenshot of CTP2 running on Linux") -This version should support CD Audio music, and also supports Ripped CD Audio compressed as ogg (like found in the GoG version). The Audio tracks should be named `Track02.ogg` to `Track11.ogg` and be in the `ctp2_program/ctp/music` folder. +The Windows version supports CD Audio music, and the Linux version supports Ripped CD Audio compressed as ogg (like found in the GoG version). The Audio tracks should be named `Track02.ogg` to `Track11.ogg` and be in the `ctp2_program/ctp/music` folder. + +As the Linux version does not support direct play from CD-rom, you need to rip the assets-files from the CD and put them on your disk. ## Building on Linux You will probably need GCC 5.x or later to build. The code doesn't seem to build on GCC 4.8. -You will need SDL 1.2, SDL_Mixer, SDL_Image and the GTK 2.0 libraries. +You will need SDL 2.0, SDL_Mixer 2.0, SDL_Image 2.0. To be able to play movies you also need ffmpeg libraries (some). You will also need `byacc` -On debian and friends, use `sudo apt install libsdl1.2-dev libsdl-mixer1.2-dev libsdl-image1.2-dev byacc gtk2.0-dev` to install them all. +On debian and friends, use `sudo apt install libsdl2-dev libsdl2-mixer-dev libsdl2-image-dev libtiff-dev libavcodec-dev libavformat-dev libswscale-dev byacc flex` to install them all. The build itself is pretty classing and straight forward: diff --git a/configure.ac b/configure.ac index 29752693f..8766e2602 100644 --- a/configure.ac +++ b/configure.ac @@ -54,7 +54,7 @@ dnl AC_PROG_LIBTOOL AM_PATH_DIRECTX AM_PATH_DXMEDIA -AM_PATH_SDL +AM_PATH_SDL2 AM_PATH_SDL_FFMPEG AC_PATH_X AC_PATH_XTRA @@ -64,15 +64,6 @@ AC_WORDS_BIGENDIAN AC_OS_DEFINES AC_OS_PATHNAMES -if test "x$ac_OpSystem" != "xWIN32" -then - PKG_CHECK_MODULES(GTK, gtk+-2.0) - AC_DEFINE(USE_GTK,1,[Use gtk+ for native dialogs]) - AC_SUBST(USE_GTK) - AC_SUBST(GTK_CFLAGS) - AC_SUBST(GTK_LIBS) -fi - AC_CHECK_HEADERS(limits.h sys/param.h) case $host in *-cygwin*) diff --git a/ctp2_code/Makefile.am b/ctp2_code/Makefile.am index 27469209e..841dfa0dc 100644 --- a/ctp2_code/Makefile.am +++ b/ctp2_code/Makefile.am @@ -10,7 +10,7 @@ SUBDIRS = \ libs \ sound -bin_PROGRAMS = ctp2 +bin_PROGRAMS = ctp/ctp2 # This hack shortens include path list, # but prohibits using a separate build dir #ctp2_code=.. @@ -38,7 +38,7 @@ CTP2_ANET_INC=-I$(ctp2_code)/libs/anet/h include $(ctp2_code)/os/autoconf/Makefile.common -ctp2_LDADD = \ +ctp_ctp2_LDADD = \ gfx/gfx_utils/libgfxgfx_utils.la \ gfx/layers/libgfxlayers.la \ gfx/spritesys/libgfxspritesys.la \ @@ -57,10 +57,10 @@ ctp2_LDADD = \ $(CTP2_LIBOSNOWIN32_LDADD) \ $(CTP2_LIBTTF_LDADD) -ctp2_LDFLAGS = \ +ctp_ctp2_LDFLAGS = \ $(CTP2_LDFLAGS) -ctp2_SOURCES = \ +ctp_ctp2_SOURCES = \ ctp/ctp2_utils/appstrings.cpp \ ctp/ctp2_utils/c3cmdline.cpp \ ctp/ctp2_utils/c3cpu.cpp \ @@ -235,6 +235,8 @@ ctp2_SOURCES = \ ui/aui_sdl/aui_sdljoystick.cpp \ ui/aui_sdl/aui_sdlkeyboard.cpp \ ui/aui_sdl/aui_sdlmouse.cpp \ + ui/aui_sdl/aui_sdlmovie.cpp \ + ui/aui_sdl/aui_sdlmoviemanager.cpp \ ui/aui_sdl/aui_sdlsound.cpp \ ui/aui_sdl/aui_sdlsurface.cpp \ ui/aui_sdl/aui_sdlui.cpp \ diff --git a/ctp2_code/ctp/c3.h b/ctp2_code/ctp/c3.h index 114d2afea..44746b644 100644 --- a/ctp2_code/ctp/c3.h +++ b/ctp2_code/ctp/c3.h @@ -43,7 +43,7 @@ // - Moved DirectX API-Version to use into "ctp2_config.h" // - Added struct for automatic debug tool initialization and // cleanup so that it is the first respective the last thing -// that is done in the program. (Oct 3rd 2005 Martin Gühmann) +// that is done in the program. (Oct 3rd 2005 Martin Gühmann) // //---------------------------------------------------------------------------- diff --git a/ctp2_code/ctp/civ3_main.cpp b/ctp2_code/ctp/civ3_main.cpp index bf1e898ea..ceb95b2bb 100644 --- a/ctp2_code/ctp/civ3_main.cpp +++ b/ctp2_code/ctp/civ3_main.cpp @@ -45,17 +45,17 @@ // - Merged GNU and MSVC code (DoFinalCleanup, CivMain). // - Option added to include multiple data directories. // - Display the main thread function name in the debugger. -// - Removed references to CivilisationDB. (Aug 20th 2005 Martin G?hmann) -// - Removed references to old SpriteStateDBs. (Aug 29th 2005 Martin G?hmann) -// - Initialized local variables. (Sep 9th 2005 Martin G?hmann) -// - Removed unused local variables. (Sep 9th 2005 Martin G?hmann) -// - Removed some unreachable code. (Sep 9th 2005 Martin G?hmann) +// - Removed references to CivilisationDB. (Aug 20th 2005 Martin Gühmann) +// - Removed references to old SpriteStateDBs. (Aug 29th 2005 Martin Gühmann) +// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) +// - Removed unused local variables. (Sep 9th 2005 Martin Gühmann) +// - Removed some unreachable code. (Sep 9th 2005 Martin Gühmann) // - Moved debug tools handling to c3.h, so that the leak reporter doesn't -// report leaks that aren't leaks. (Oct 3rd 2005 Matzin G?hmann) +// report leaks that aren't leaks. (Oct 3rd 2005 Matzin Gühmann) // - Added version to crash.txt -// - USE_LOGGING now works in a final version. (30-Jun-2008 Martin G?hmann) +// - USE_LOGGING now works in a final version. (30-Jun-2008 Martin Gühmann) // - The log files are now only opened and closed once, this speeds up -// debugging significantly. (09-Aug-2008 Martin G?hmann) +// debugging significantly. (09-Aug-2008 Martin Gühmann) // //---------------------------------------------------------------------------- // @@ -72,7 +72,6 @@ #include "ancientwindows.h" #include "appstrings.h" #include "aui.h" -#include "aui_directmoviemanager.h" #include "aui_Factory.h" #include "aui_ldl.h" #include "background.h" @@ -169,16 +168,13 @@ #include #endif #if defined(USE_SDL) -#include -#include +#include +#include #include "aui_sdlkeyboard.h" #endif #ifdef HAVE_X11 #include #endif -#ifdef USE_GTK -#include -#endif #if defined(_DEBUG) #include "debug.h" // Os::SetThreadName @@ -237,7 +233,7 @@ sint32 g_modalWindow = 0; BOOL g_helpMode = TRUE; static uint32 s_scrollcurtick =0; -static uint32 s_scrolllasttick=0; +static uint32 s_lastscrolltick=0; static sint32 s_scrolltime =k_SMOOTH_START_TIME; static uint32 s_accelTickStart = 0; @@ -276,11 +272,7 @@ BOOL g_runInBackground = FALSE; BOOL g_runSpriteEditor = FALSE; BOOL g_eventLog = FALSE; -#if 0 -uint32 g_SDL_flags = SDL_DOUBLEBUF | SDL_HWSURFACE; -#else -uint32 g_SDL_flags = 0; //See ctp2_code/ui/aui_common/aui_ui.cpp //SEB Pandora -#endif +uint32 g_SDL_flags = 0; BOOL g_use_profile_process = FALSE; @@ -561,12 +553,7 @@ int ui_Initialize(void) g_c3ui->RegisterObject(aui_Factory::new_Keyboard(auiErr)); SPLASH_STRING("Creating Movie manager..."); -#if defined(__AUI_USE_SDL__) - //SDL movie manager is in aui_movie.cpp - g_c3ui->RegisterObject(new aui_MovieManager()); -#else - g_c3ui->RegisterObject(new aui_DirectMovieManager()); -#endif + g_c3ui->RegisterObject(g_c3ui->CreateMovieManager()); SPLASH_STRING("Starting Mouse..."); auiErr = g_c3ui->TheMouse()->Start(); @@ -660,7 +647,6 @@ bool ui_CheckForScroll(void) g_tiledMap->SetScrolling(false); - s_scrolllasttick = s_scrollcurtick; s_scrollcurtick = GetTickCount(); if (!g_c3ui->TheMouse()) @@ -679,6 +665,9 @@ bool ui_CheckForScroll(void) // const int k_MAX_SMOOTH_SCROLL = 64; const int k_TICKS_PER_ACCELERATION = 50; + /* Limit the number of scroll actions per second. */ + const int k_NUMBER_OF_SCROLL_ACTIONS = 20; + const int k_TICKS_PER_SCROLL = 1000 / k_NUMBER_OF_SCROLL_ACTIONS; sint32 deltaX = 0, deltaY = 0; @@ -778,11 +767,7 @@ bool ui_CheckForScroll(void) isMouseScrolling = true; } - if(scrolled) { - if (isMouseScrolling) - g_cursorManager->SetCursor(scrollCursor); - if(!scrolled_last_time) { scroll_start = GetTickCount(); } @@ -808,6 +793,8 @@ bool ui_CheckForScroll(void) lastdeltaX = deltaX; lastdeltaY = deltaY; + if (isMouseScrolling) + g_cursorManager->SetCursor(scrollCursor); g_tiledMap->SetScrolling(true); uint32 accellTickDelta = s_scrollcurtick - s_accelTickStart; @@ -831,9 +818,12 @@ bool ui_CheckForScroll(void) if (g_smoothScroll) g_tiledMap->ScrollMapSmooth(smoothX, smoothY); - else - g_tiledMap->ScrollMap(deltaX, deltaY); - + else { + if ((s_scrollcurtick - s_lastscrolltick) > k_TICKS_PER_SCROLL) { + s_lastscrolltick = GetTickCount(); + g_tiledMap->ScrollMap(deltaX, deltaY); + } + } } else { @@ -1038,8 +1028,6 @@ void AtExitProc(void) Mix_CloseAudio(); # endif -g_mouseShouldTerminateThread = TRUE; - // Destroy the mutex used for the secondary keyboard event queue #ifdef __AUI_USE_SDL__ SDL_DestroyMutex(g_secondaryKeyboardEventQueueMutex); @@ -1168,13 +1156,15 @@ void ParseCommandLine(PSTR szCmdLine) g_runSpriteEditor = (NULL != strstr(szCmdLine, "runspriteeditor")); #if defined(__AUI_USE_SDL__) - if (strstr(szCmdLine, "fullscreen")) - g_SDL_flags = g_SDL_flags|SDL_FULLSCREEN; - if (strstr(szCmdLine, "hwsurface")) - g_SDL_flags = g_SDL_flags|SDL_HWSURFACE; - else g_SDL_flags = g_SDL_flags|SDL_SWSURFACE; - if (strstr(szCmdLine, "openglblit")) - g_SDL_flags = g_SDL_flags|SDL_OPENGLBLIT; + if (strstr(szCmdLine, "fullscreen")) { + g_SDL_flags = g_SDL_flags | SDL_WINDOW_FULLSCREEN_DESKTOP; + } + if (strstr(szCmdLine, "hwsurface")) { + printf("SDL2 does not support hwsurface option"); + } + if (strstr(szCmdLine, "openglblit")) { + printf("SDL2 uses OpenGL automatically"); + } #endif g_eventLog = (NULL != strstr(szCmdLine, "eventlog")); @@ -1575,16 +1565,9 @@ int WINAPI CivMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, } } #endif -#ifdef USE_GTK - gtk_init(&iCmdShow, &pSzCmdLine); -#endif appstrings_Initialize(); -#ifdef USE_GTK -// gtk_set_locale(); - gtk_init(&iCmdShow, &pSzCmdLine); -#endif std::setlocale(LC_COLLATE, appstrings_GetString(APPSTR_LOCALE)); std::setlocale(LC_NUMERIC, "C"); @@ -1691,36 +1674,51 @@ int WINAPI CivMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, for (gDone = FALSE; !gDone; ) { + uint32 frameStartTick = GetTickCount(); g_civApp->Process(); - //fprintf(stderr, "%s L%d: g_civApp->Process() done!\n", __FILE__, __LINE__); + //fprintf(stderr, "%s L%d: g_civApp->Process() done!\n", __FILE__, __LINE__); #ifdef __AUI_USE_SDL__ SDL_Event event; while (!g_letUIProcess) { // There are breaks, too ;) - // Throttle the loop a bit to prevent 100% CPU usage in idle state. - // FIXME: implement blocking loop with SDL_WaitEvent(). - if (!SDL_PollEvent(NULL)) { - SDL_Delay(30); - break; + + static const int FRAMES_PER_SECOND = 30; + static const int TICKS_PER_FRAME = 1000 / FRAMES_PER_SECOND; + const int frameTicksLeft = frameStartTick + TICKS_PER_FRAME - GetTickCount(); + if (frameTicksLeft > 0) { + if (!SDL_WaitEventTimeout(NULL, frameTicksLeft)) { + break; + } + } else { + if (!SDL_PollEvent(NULL)) { + break; + } } - int n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, - ~(SDL_EVENTMASK(SDL_MOUSEMOTION) | SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN) | SDL_EVENTMASK(SDL_MOUSEBUTTONUP))); + int n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_MOUSEMOTION-1); if (0 > n) { - fprintf(stderr, "%s L%d: SDL_PeepEvents: Still events stored! Error?: %s\n", __FILE__, __LINE__, SDL_GetError()); - + fprintf(stderr, "%s L%d: SDL_PeepEvents: Still events stored! Error?: %s\n", __FILE__, __LINE__, SDL_GetError()); break; } if (0 == n) { - // other events are handled in other threads - // or no more events - break; + n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEWHEEL+1, SDL_LASTEVENT); + if (0 > n) { + fprintf(stderr, "%s L%d: SDL_PeepEvents: Still events stored! Error?: %s\n", __FILE__, __LINE__, SDL_GetError()); + break; + } + + if (0 == n) { + // other events are handled in other threads + // or no more events + break; + } } - if (SDL_QUIT == event.type) + if (SDL_QUIT == event.type) { gDone = TRUE; + } // If a keyboard event then we must reenqueue it so that aui_sdlkeyboard has a chance to look at it if (event.type == SDL_KEYDOWN || event.type == SDL_KEYUP) @@ -1819,8 +1817,8 @@ int SDLMessageHandler(const SDL_Event &event) // TODO: Determine what the 'swallowNextChar' variable // is for, and, if necessary, implement appropriate // code in the SDL sections to perform the same function. - SDLKey key = event.key.keysym.sym; - SDLMod mod = event.key.keysym.mod; + SDL_Keycode key = event.key.keysym.sym; + Uint16 mod = event.key.keysym.mod; WPARAM wp = '\0'; switch (key) { #define SDLKCONV(sdl_name, char) \ @@ -1891,16 +1889,16 @@ int SDLMessageHandler(const SDL_Event &event) //SDLKCONVSHIFT(SDLK_F13, '' + 128, '\0'); //SDLKCONVSHIFT(SDLK_F14, '' + 128, '\0'); //SDLKCONVSHIFT(SDLK_F15, '' + 128, '\0'); - SDLKCONV(SDLK_KP0, '0'); - SDLKCONV(SDLK_KP1, '1'); - SDLKCONV(SDLK_KP2, '2'); - SDLKCONV(SDLK_KP3, '3'); - SDLKCONV(SDLK_KP4, '4'); - SDLKCONV(SDLK_KP5, '5'); - SDLKCONV(SDLK_KP6, '6'); - SDLKCONV(SDLK_KP7, '7'); - SDLKCONV(SDLK_KP8, '8'); - SDLKCONV(SDLK_KP9, '9'); + SDLKCONV(SDLK_KP_0, '0'); + SDLKCONV(SDLK_KP_1, '1'); + SDLKCONV(SDLK_KP_2, '2'); + SDLKCONV(SDLK_KP_3, '3'); + SDLKCONV(SDLK_KP_4, '4'); + SDLKCONV(SDLK_KP_5, '5'); + SDLKCONV(SDLK_KP_6, '6'); + SDLKCONV(SDLK_KP_7, '7'); + SDLKCONV(SDLK_KP_8, '8'); + SDLKCONV(SDLK_KP_9, '9'); SDLKCONV(SDLK_KP_PERIOD, '.'); SDLKCONV(SDLK_KP_DIVIDE, '/'); SDLKCONV(SDLK_KP_MULTIPLY, '*'); diff --git a/ctp2_code/ctp/civapp.cpp b/ctp2_code/ctp/civapp.cpp index d89e9ef0d..ab0b9b02f 100644 --- a/ctp2_code/ctp/civapp.cpp +++ b/ctp2_code/ctp/civapp.cpp @@ -39,9 +39,9 @@ // - Keep the user's leader name when the data is consistent. // - Skip begin turn handling when loading from a file. // - Fixed a repetitive memory leak in the Great Libary caused by -// scenario loading, by Martin G?hmann. +// scenario loading, by Martin Gühmann. // - Removed some redundant code, because it is already done -// somewhere else, by Martin G?hmann. +// somewhere else, by Martin Gühmann. // //---------------------------------------------------------------------------- // @@ -65,32 +65,32 @@ // - Used the new ColorSet option to select civilisation colors. // - Memory leak repaired: clean up the turn counter override information. // - Hot seat handling improved. -// - Static member of StatusBar is now deleted correctly, by Martin G?hmann. +// - Static member of StatusBar is now deleted correctly, by Martin Gühmann. // - Cleaned up music screen. // - The civilisation index from the profile is now reset if it is too high. -// This prevents the game from crashing. - April 12th 2005 Martin G?hmann +// This prevents the game from crashing. - April 12th 2005 Martin Gühmann // - Added crash prevention during game loading. // - Added another civilisation index check. // - Option added to include multiple data directories. // - Added Slic segment cleanup. -// - Replaced old civilisation database by new one. (Aug 22nd 2005 Martin G?hmann) -// - Made progress bar more fluently. (Aug 22nd 2005 Martin G?hmann) -// - Removed the old endgame and installation databases. (Aug 29th 2005 Martin G?hmann) +// - Replaced old civilisation database by new one. (Aug 22nd 2005 Martin Gühmann) +// - Made progress bar more fluently. (Aug 22nd 2005 Martin Gühmann) +// - Removed the old endgame and installation databases. (Aug 29th 2005 Martin Gühmann) // - Removed old sprite state databases, removed olf good's icon -// database (unused), replaced old risk database by new one. (Aug 29th 2005 Martin G?hmann) -// - The right color set is now selected afterwards the ProfileDB is available. (Aug 29th 2005 Martin G?hmann) -// - Added cleanup of gaia controller and info window. (Sep 13th 2005 Martin G?hmann) -// - Added ArmyData and Network cleanup. (Sep 25th 2005 Martin G?hmann) -// - Added graphicsresscreen_Cleanup. (Sep 25th 2005 Martin G?hmann) -// - Replaced old difficulty database by new one. (April 29th 2006 Martin G?hmann) -// - Replaced old pollution database by new one. (July 15th 2006 Martin G?hmann) -// - Replaced old global warming database by new one. (July 15th 2006 Martin G?hmann) -// - Added new map icon database. (3-Mar-2007 Martin G?hmann) -// - Replaced old map database by new one. (27-Mar-2007 Martin G?hmann) -// - Replaced old concept database by new one. (31-Mar-2007 Martin G?hmann) -// - Replaced old const database by new one. (5-Aug-2007 Martin G?hmann) -// - Fixed PBEM BeginTurn event execution. (27-Oct-2007 Martin G?hmann) -// - Games can now be saved if the visible player is a robot. (30-Jan-2008 Martin G?hmann) +// database (unused), replaced old risk database by new one. (Aug 29th 2005 Martin Gühmann) +// - The right color set is now selected afterwards the ProfileDB is available. (Aug 29th 2005 Martin Gühmann) +// - Added cleanup of gaia controller and info window. (Sep 13th 2005 Martin Gühmann) +// - Added ArmyData and Network cleanup. (Sep 25th 2005 Martin Gühmann) +// - Added graphicsresscreen_Cleanup. (Sep 25th 2005 Martin Gühmann) +// - Replaced old difficulty database by new one. (April 29th 2006 Martin Gühmann) +// - Replaced old pollution database by new one. (July 15th 2006 Martin Gühmann) +// - Replaced old global warming database by new one. (July 15th 2006 Martin Gühmann) +// - Added new map icon database. (3-Mar-2007 Martin Gühmann) +// - Replaced old map database by new one. (27-Mar-2007 Martin Gühmann) +// - Replaced old concept database by new one. (31-Mar-2007 Martin Gühmann) +// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) +// - Fixed PBEM BeginTurn event execution. (27-Oct-2007 Martin Gühmann) +// - Games can now be saved if the visible player is a robot. (30-Jan-2008 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -1250,7 +1250,7 @@ sint32 CivApp::InitializeApp(HINSTANCE hInstance, int iCmdShow) CoInitialize(NULL); #endif #ifdef __AUI_USE_SDL__ - Uint32 flags = (SDL_INIT_EVERYTHING | SDL_INIT_EVENTTHREAD) & ~SDL_INIT_AUDIO; //why no audio? + Uint32 flags = (SDL_INIT_EVERYTHING | SDL_INIT_EVENTS) & ~SDL_INIT_AUDIO; //why no audio? #if defined(_DEBUG) || defined(DEBUG) flags |= SDL_INIT_NOPARACHUTE; #endif// _DEBUG || DEBUG @@ -1274,8 +1274,10 @@ sint32 CivApp::InitializeApp(HINSTANCE hInstance, int iCmdShow) g_logCrashes = g_theProfileDB->GetEnableLogs(); InitDataIncludePath(); +#if !defined(USE_SDL) c3files_InitializeCD(); g_civPaths->InitCDPath(); +#endif // USE_SDL GreatLibrary::Initialize_Great_Library_Data(); display_Initialize(hInstance, iCmdShow); @@ -1636,7 +1638,7 @@ sint32 CivApp::InitializeGameUI(void) return 0; } -sint32 CivApp::InitializeGame(CivArchive &archive) +sint32 CivApp::InitializeGame(CivArchive *archive) { ProgressWindow::BeginProgress( g_theProgressWindow, @@ -1721,9 +1723,9 @@ sint32 CivApp::InitializeGame(CivArchive &archive) g_theProgressWindow->StartCountingTo( 610 ); - if(g_isScenario && (&archive != NULL && + if(g_isScenario && archive && (g_startInfoType != STARTINFOTYPE_NONE || - g_saveFileVersion < gamefile_CurrentVersion()))) { + g_saveFileVersion < gamefile_CurrentVersion())) { for(sint32 i = 0; i < k_MAX_PLAYERS; i++) { if(g_player[i]) { @@ -1784,7 +1786,7 @@ sint32 CivApp::InitializeGame(CivArchive &archive) GraphicsOptions::Initialize(); SPLASH_STRING("Initializing Tile Engine..."); - tile_Initialize(&archive != NULL); + tile_Initialize(archive != NULL); g_theProgressWindow->StartCountingTo( 660 ); @@ -1814,7 +1816,7 @@ sint32 CivApp::InitializeGame(CivArchive &archive) if(!g_network.IsActive() && !g_network.IsNetworkLaunch()) { - if ((&archive == NULL) || // launch button + if ((archive == NULL) || // launch button ((g_startInfoType != STARTINFOTYPE_NONE) && g_isScenario) // scenario start ) { @@ -1829,7 +1831,7 @@ sint32 CivApp::InitializeGame(CivArchive &archive) g_theProgressWindow->StartCountingTo( 720 ); if(!g_network.IsActive()) { - if (NULL == &archive || + if (NULL == archive || (g_saveFileVersion >= 42 && (g_isScenario && g_startInfoType != STARTINFOTYPE_NOLOCS))) { @@ -1844,7 +1846,7 @@ sint32 CivApp::InitializeGame(CivArchive &archive) g_theProgressWindow->StartCountingTo( 740 ); - if(g_turn->IsEmail() && NULL != &archive) { + if(g_turn->IsEmail() && archive) { g_selected_item->KeyboardSelectFirstUnit(); if(g_selected_item->GetState() != SELECT_TYPE_LOCAL_ARMY && (g_player[g_selected_item->GetVisiblePlayer()]->m_all_cities->Num() > 0)) { @@ -1867,14 +1869,14 @@ sint32 CivApp::InitializeGame(CivArchive &archive) g_theProgressWindow->StartCountingTo( 760 ); - if ((&archive) && g_turn->IsHotSeat()) + if (archive && g_turn->IsHotSeat()) { // Indicate the resuming player when loading a saved hotseat game g_turn->SendNextPlayerMessage(); } else if (g_selected_item) { - if (!&archive) + if (!archive) { g_selected_item->Refresh(); } @@ -2009,7 +2011,7 @@ sint32 InitializeSpriteEditorUI(void) return 0; } -sint32 CivApp::InitializeSpriteEditor(CivArchive &archive) +sint32 CivApp::InitializeSpriteEditor(CivArchive *archive) { ProgressWindow::BeginProgress( g_theProgressWindow, @@ -2063,7 +2065,7 @@ sint32 CivApp::InitializeSpriteEditor(CivArchive &archive) g_theProgressWindow->StartCountingTo( 720 ); - if ( (&archive != NULL) + if (archive && (g_startInfoType != STARTINFOTYPE_NONE || g_saveFileVersion < gamefile_CurrentVersion() ) @@ -2088,7 +2090,7 @@ sint32 CivApp::InitializeSpriteEditor(CivArchive &archive) g_theProgressWindow->StartCountingTo( 750 ); SPLASH_STRING("Initializing Tile Engine..."); - tile_Initialize(&archive != NULL); + tile_Initialize(archive != NULL); g_theProgressWindow->StartCountingTo( 760 ); @@ -2109,7 +2111,7 @@ sint32 CivApp::InitializeSpriteEditor(CivArchive &archive) g_turn->BeginNewTurn(FALSE); if(!g_network.IsActive()) { - if (NULL == &archive || + if (NULL == archive || (g_saveFileVersion >= 42 && (g_isScenario && g_startInfoType != STARTINFOTYPE_NOLOCS))) { @@ -2124,7 +2126,7 @@ sint32 CivApp::InitializeSpriteEditor(CivArchive &archive) g_theProgressWindow->StartCountingTo( 800 ); - if(g_turn->IsEmail() && NULL != &archive) { + if(g_turn->IsEmail() && archive) { g_selected_item->KeyboardSelectFirstUnit(); if(g_selected_item->GetState() != SELECT_TYPE_LOCAL_ARMY && (g_player[g_selected_item->GetVisiblePlayer()]->m_all_cities->Num() > 0)) { @@ -2365,8 +2367,7 @@ sint32 CivApp::ProcessUI(const uint32 target_milliseconds, uint32 &used_millisec #ifdef __AUI_USE_SDL__ // Because of the way keyboard events are handled in SDL, we // need to escape this loop if there are any SDL_KeyEvents pending - if (SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, - SDL_EVENTMASK(SDL_KEYUP) | SDL_EVENTMASK(SDL_KEYDOWN))) { + if (SDL_PeepEvents(NULL, 1, SDL_PEEKEVENT, SDL_KEYDOWN, SDL_KEYUP)) { break; } #endif @@ -2586,12 +2587,12 @@ sint32 CivApp::Process(void) sint32 CivApp::StartGame(void) { - return InitializeGame((*(CivArchive *)(NULL))); + return InitializeGame(NULL); } sint32 CivApp::StartSpriteEditor(void) { - return InitializeSpriteEditor((*(CivArchive *)(NULL))); + return InitializeSpriteEditor(NULL); } sint32 CivApp::EndGame(void) diff --git a/ctp2_code/ctp/civapp.h b/ctp2_code/ctp/civapp.h index f8ca0b3ca..4284b4657 100644 --- a/ctp2_code/ctp/civapp.h +++ b/ctp2_code/ctp/civapp.h @@ -85,7 +85,7 @@ class CivApp sint32 InitializeApp(HINSTANCE hInstance, int iCmdShow); bool InitializeAppDB(void); sint32 InitializeAppDB(CivArchive &archive); - sint32 InitializeGame(CivArchive &archive); + sint32 InitializeGame(CivArchive *archive); bool IsGameLoaded(void) const { @@ -138,7 +138,7 @@ class CivApp void CleanupGameUI(void); void InitializeAppUI(void); sint32 InitializeGameUI(void); - sint32 InitializeSpriteEditor(CivArchive &archive); + sint32 InitializeSpriteEditor(CivArchive *archive); void PostLoadSaveGameMapAction(MBCHAR const *); sint32 ProcessAI(); sint32 ProcessNet(const uint32 target_milliseconds, uint32 &used_milliseconds); diff --git a/ctp2_code/ctp/ctp2_utils/c3cmdline.cpp b/ctp2_code/ctp/ctp2_utils/c3cmdline.cpp index f4d8dd475..b5b26e4d1 100644 --- a/ctp2_code/ctp/ctp2_utils/c3cmdline.cpp +++ b/ctp2_code/ctp/ctp2_utils/c3cmdline.cpp @@ -34,8 +34,8 @@ // // - Removed non-standard include file . // - Standardised min/max usage. -// - Replaced old civilisation database by new one. (Aug 20th 2005 Martin Gühmann) -// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) +// - Replaced old civilisation database by new one. (Aug 20th 2005 Martin Gühmann) +// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -5853,44 +5853,48 @@ void FastRoundCommand::Execute(sint32 argc, char **argv) #if __AUI_USE_SDL__ while (1) { - int n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, - ~(SDL_EVENTMASK(SDL_MOUSEMOTION) | SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN) | - SDL_EVENTMASK(SDL_MOUSEBUTTONUP))); + int n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_MOUSEMOTION - 1); if (0 > n) { - fprintf(stderr, "[FastRoundCommand::Execute] PeepEvents failed: %s\n", - SDL_GetError()); + fprintf(stderr, "[FastRoundCommand::Execute] PeepEvents failed:\n%s\n", SDL_GetError()); break; } if (0 == n) { - // other events are handled in other threads - // or no more events - break; + n = SDL_PeepEvents(&event, 1, SDL_GETEVENT, SDL_MOUSEWHEEL + 1, SDL_LASTEVENT); + if (0 > n) { + fprintf(stderr, "[FastRoundCommand::Execute] PeepEvents failed:\n%s\n", SDL_GetError()); + break; + } + if (0 == n) { + // other events are handled in other threads + // or no more events + break; + } + } + if (SDL_QUIT == event.type) { + gDone = TRUE; + } + if (SDL_KEYDOWN == event.type) + { + SDL_KeyboardEvent key = event.key; + if (SDLK_ESCAPE == key.keysym.sym) + i = n; } - if (SDL_QUIT == event.type) + } #else while (PeekMessage(&msg, gHwnd, 0, 0, PM_REMOVE) && !g_letUIProcess) { - if (msg.message == WM_QUIT) -#endif + if (msg.message == WM_QUIT) { gDone = TRUE; -#ifndef __AUI_USE_SDL__ + } TranslateMessage(&msg); if (msg.message == WM_CHAR) { if ((MBCHAR)msg.wParam == 0x1B) i = n; } - DispatchMessage(&msg); -#else - if (SDL_KEYDOWN == event.type) - { - SDL_KeyboardEvent key = event.key; - if (SDLK_ESCAPE == key.keysym.sym) - i = n; - } -#endif } +#endif g_letUIProcess = FALSE; } while ((g_selected_item->GetCurPlayer() != g_selected_item->GetVisiblePlayer()) && diff --git a/ctp2_code/ctp/ctp2_utils/c3debug.cpp b/ctp2_code/ctp/ctp2_utils/c3debug.cpp index 00f3647d6..d27d1056b 100644 --- a/ctp2_code/ctp/ctp2_utils/c3debug.cpp +++ b/ctp2_code/ctp/ctp2_utils/c3debug.cpp @@ -49,6 +49,7 @@ #include "netconsole.h" #include "c3files.h" +extern BOOL g_noAssertDialogs; uint32 g_debug_mask = k_DBG_NONE; static int g_useMask; @@ -317,16 +318,17 @@ void c3debug_Assert(char const *s, char const * file, int line) MBCHAR str[1024]; sprintf(str, "Assertion (%s) Failed in File:%s, Line:%ld\n", s, file, line); fprintf(stderr, str); - // sint32 result = MessageBox(NULL, str, "Assert", MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION); + sint32 result = g_noAssertDialogs ? IDIGNORE + : MessageBox(NULL, str, "Assert", MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION); - // if(result == IDRETRY) - // { + if(result == IDRETRY) + { std::raise(SIGINT); - // } - // else if(result == IDABORT) - // { - // exit(-1); - // } + } + else if(result == IDABORT) + { + exit(-1); + } #endif #endif } diff --git a/ctp2_code/ctp/ctp2_utils/c3files.cpp b/ctp2_code/ctp/ctp2_utils/c3files.cpp index d041e5a9b..8cad75dbe 100644 --- a/ctp2_code/ctp/ctp2_utils/c3files.cpp +++ b/ctp2_code/ctp/ctp2_utils/c3files.cpp @@ -44,8 +44,9 @@ #include "pointerlist.h" #include "profileDB.h" #include "soundmanager.h" +#if !defined(USE_SDL) #include "tracklen.h" - +#endif // USE_SDL #ifdef HAVE_STRING_H #include #endif @@ -81,26 +82,19 @@ extern C3UI * g_c3ui; +#if !defined(USE_SDL) + namespace { -#ifdef _WIN32 // #ifndef USE_SDL DriveIdType const DRIVE_FIRST = 'A'; DriveIdType const DRIVE_LAST = 'Z'; DriveIdType const DRIVE_UNDETERMINED = '\0'; size_t const DRIVE_COUNT = 1 + (DRIVE_LAST - DRIVE_FIRST); -#else - DriveIdType const DRIVE_FIRST = 0; - DriveIdType DRIVE_LAST = -1; - DriveIdType const DRIVE_UNDETERMINED = -1; - size_t DRIVE_COUNT = 0; -#endif size_t const VOLUME_NAME_SIZE = 32; bool g_hasCD = false; -#ifdef _WIN32 // #ifndef USE_SDL bool IsCD[DRIVE_COUNT]; -#endif MBCHAR VolumeName[VOLUME_NAME_SIZE]; DriveIdType WhichCD = DRIVE_UNDETERMINED; @@ -111,6 +105,8 @@ namespace #define k_CTP_CD_VOLUME_NAME "CTP2" +#endif // USE_SDL + FILE* c3files_fopen(C3DIR dirID, MBCHAR const * s1, MBCHAR const * s2, bool checkScenario) { MBCHAR s[_MAX_PATH]; @@ -516,6 +512,8 @@ const MBCHAR *c3files_GetCTPHomeDir() return NULL; } +#if !defined(USE_SDL) + bool c3files_HasLegalCD() { bool success = false; @@ -536,7 +534,6 @@ bool c3files_HasLegalCD() if (!success) { -#if defined(WIN32) int const rval = MessageBox (g_c3ui ? g_c3ui->TheHWND() : NULL, appstrings_GetString(APPSTR_INSERTCDROM), @@ -550,17 +547,9 @@ bool c3files_HasLegalCD() if (IDCANCEL == rval) { -#else - c3errors_ErrorDialog(appstrings_GetString(APPSTR_CDROM), - appstrings_GetString(APPSTR_NEEDCDROM) - ); -#endif - // Do not annoy the user with more messages after cancelling exit(-1); -#if defined(WIN32) } -#endif if (g_c3ui) { @@ -579,14 +568,6 @@ bool c3files_HasLegalCD() void c3files_InitializeCD(void) { -#if defined(__linux__) - int rc = SDL_Init(SDL_INIT_CDROM); - if(0 != rc) - { - fprintf(stderr, "Could not initialize CDROM:\n%s\n", SDL_GetError()); - return; - } -#endif c3files_GetCDDrives(); (void) c3files_FindCDByName(k_CTP_CD_VOLUME_NAME); } @@ -601,194 +582,6 @@ DriveIdType c3files_GetCtpCdId(void) return WhichCD; } -const MBCHAR *c3files_GetCDDriveMount(MBCHAR *buf, size_t size, - DriveIdType cdIndex) -{ - if(buf == NULL) - return NULL; - - MBCHAR *cdDriveName = c3files_GetVolumeName(cdIndex); - - if(cdDriveName == NULL) - return NULL; - -#if defined(WIN32) - if(strlen(cdDriveName) >= size) - return NULL; - - strcpy(buf, cdDriveName); - return buf; -#elif defined(LINUX) - MBCHAR tempPath[_MAX_PATH] = {0}; - const size_t mntInfoCnt = 2; - // Do not change order of mntInfo - const MBCHAR *mntInfo[mntInfoCnt] = {_PATH_MOUNTED, _PATH_MNTTAB }; - const size_t mntOptsCnt = 23; - int lerrno = errno; - typedef struct - { - const char *name; - unsigned long flag; - bool clear; - } mount_opt_t; - const mount_opt_t mntOpts[mntOptsCnt] = { - { MNTOPT_RO, MS_RDONLY, false }, - { MNTOPT_RW, MS_RDONLY, true }, - { MNTOPT_NOSUID, MS_NOSUID, false }, - { MNTOPT_SUID, MS_NOSUID, true }, - { "nodev", MS_NODEV, false }, - { "dev", MS_NODEV, true }, - { "noexec", MS_NOEXEC, false }, - { "exec", MS_NOEXEC, true }, - { "sync", MS_SYNCHRONOUS, false }, - { "async", MS_SYNCHRONOUS, true }, - { "remount", MS_REMOUNT, false }, - { "lock", MS_MANDLOCK, false }, - { "nolock", MS_MANDLOCK, true }, - { "dirsync", MS_DIRSYNC, false }, - { "noatime", MS_NOATIME, false }, - { "atime", MS_NOATIME, true }, - { "nodiratime", MS_NODIRATIME, false },/// \todo: check string - { "bind", MS_BIND, false }, -// { MS_MOVE }, // for /bin/mount -// { MS_REC }, - { "verbose", MS_VERBOSE, false }, - { "acl", MS_POSIXACL, false }, - { "noacl", MS_POSIXACL, true }, -// { MS_ACTIVE }, - { "nouser", MS_NOUSER, false }, - { "user", MS_NOUSER, true } - }; - - BOOL cdrLink = FALSE; - MBCHAR devlink[_MAX_PATH] = {0}; - char *fulllink = NULL; - struct stat st = {0}; - - if(lstat(cdDriveName, &st) == -1) - { - for(sint32 i = 0; i < strlen(cdDriveName); ++i) - { - cdDriveName[i] = tolower(cdDriveName[i]); - } - - if(lstat(cdDriveName, &st) == -1) - { - return NULL; - } - } - - if(S_ISLNK(st.st_mode)) - { - int len = readlink(cdDriveName, devlink, _MAX_PATH); - if((len > 0) && (len < _MAX_PATH)) - { - - cdrLink = TRUE; - devlink[len] = '\0'; - strcpy(tempPath, cdDriveName); - char *dn = dirname(tempPath); - if(dn) - strcpy(tempPath, dn); - - strcat(tempPath, FILE_SEP); - strcat(tempPath, devlink); - fulllink = _fullpath(NULL, tempPath, 0); - } - } - - for(size_t u = 0; u < mntInfoCnt; u++) - { - FILE *mounts = setmntent(mntInfo[u], "r"); - - if(mounts) - { - struct mntent *mntent; - while(mntent = getmntent(mounts)) - { - if((mntent->mnt_fsname == NULL) || - (mntent->mnt_dir == NULL) || - (mntent->mnt_type == NULL)) - continue; - - if(strcmp(mntent->mnt_type, MNTTYPE_IGNORE) == 0) - if(mntent->mnt_type == MNTTYPE_IGNORE) - continue; - - if( strcasestr(mntent->mnt_dir, cdDriveName) != NULL - || strcasecmp(cdDriveName, mntent->mnt_fsname) == 0 - || (cdrLink && (!strcasecmp(devlink, mntent->mnt_fsname))) - || ((fulllink != NULL) && (!strcasecmp(fulllink, mntent->mnt_fsname))) - ) - { - const MBCHAR *ret = NULL; - // Mounted? - if(u == 0) - { - strncpy(buf, mntent->mnt_dir, size); - ret = buf; - // Not mounted fstab entry - } - else if(u == 1) - { - unsigned long flags = MS_MGC_VAL; - if(hasmntopt(mntent, "defaults")) - { - flags |= (MS_NOUSER); - } - for(size_t f = 0; f < mntOptsCnt; f++) - { - if(hasmntopt(mntent, mntOpts[f].name)) - if(mntOpts[f].clear) - flags &= ~mntOpts[f].flag; - else - flags |= mntOpts[f].flag; - } - errno = 0; - int rc = mount(mntent->mnt_fsname, - mntent->mnt_dir, - mntent->mnt_type, - flags, 0); - lerrno = errno; //preserve errno value of mount over other library calls! - if(0 == rc) - { - strncpy(buf, mntent->mnt_dir, size); - ret = buf; - } - else - { - fprintf(stderr, "%s L%d: CD mount error occured: ", __FILE__, __LINE__); - perror(strerror(lerrno)); - } - } - - endmntent(mounts); - if(fulllink) - { - free(fulllink); - fulllink = 0; - } - - return ret; - } - } - endmntent(mounts); - } - } - if(fulllink) - { - free(fulllink); - fulllink = 0; - } - - return NULL; -#else -/* Seriously? A game mounting a filesystem? */ -strlcpy(buf, cdDriveName, size); -return buf; -#endif -} - namespace { @@ -809,7 +602,6 @@ namespace //---------------------------------------------------------------------------- void c3files_GetCDDrives(void) { -#if defined(WIN32) // #ifndef USE_SDL MBCHAR drivepath[4]; // letter + : + dir seperator + zero strcpy(drivepath, " :" FILE_SEP); @@ -827,19 +619,6 @@ void c3files_GetCDDrives(void) IsCD[i] = false; } } -#else - int CDCnt = SDL_CDNumDrives(); - Assert(CDCnt >= 0); - if (CDCnt < 0) - { - DRIVE_COUNT = 0; - } - else - { - DRIVE_COUNT = CDCnt; - } - DRIVE_LAST = DRIVE_COUNT - 1; -#endif } //---------------------------------------------------------------------------- @@ -859,7 +638,6 @@ void c3files_GetCDDrives(void) //---------------------------------------------------------------------------- MBCHAR * c3files_GetVolumeName(DriveIdType id) { -#if defined(WIN32) MBCHAR drivepath[4]; // letter + : + dir seperator + zero strcpy(drivepath, " :" FILE_SEP); drivepath[0] = id; @@ -884,69 +662,6 @@ MBCHAR * c3files_GetVolumeName(DriveIdType id) } return NULL; - -#elif defined(LINUX) - /// \todo Add code to determine beginsector of iso_primary_sector - /// On a German ctp2 cd, it starts on sector 16 (byte 16 << 11 = 0x8000) - const MBCHAR *cd_dev = SDL_CDName(id); - FILE *cd = fopen(cd_dev, "rb"); - int lerrno = errno; - if (cd == NULL) - { - fprintf(stderr, "%s\n", strerror(lerrno)); - return NULL; - } - - int rc = fseek(cd, 0x8000, SEEK_SET); - lerrno = errno; - if (rc != 0) - { - fprintf(stderr, "%s\n", strerror(lerrno)); - fclose(cd); - return NULL; - } - - struct iso_primary_descriptor ipd; - memset(&ipd, 0, sizeof(ipd)); - size_t s = fread(&ipd, 1, sizeof(ipd), cd); - lerrno = errno; - if (s != sizeof(ipd)) - { - fprintf(stderr, "Failed reading %d bytes: %s\n", sizeof(ipd), - strerror(lerrno)); - fclose(cd); - return NULL; - } - unsigned int i = 0; - s = std::min(sizeof(ipd.volume_id), sizeof(VolumeName)); - assert(i < s); - - while (i < s) - { - if ('\0' == ipd.volume_id[i]) - { - VolumeName[i] = '\0'; - return VolumeName; - } - if ((!isalnum(ipd.volume_id[i])) && (!isspace(ipd.volume_id[i]))) - { - return NULL; - } - VolumeName[i] = ipd.volume_id[i]; - i++; - } - i--; - - // Win32 Compat: GetVolumeInformation does not return ending spaces - while ((i > 0) && isspace(VolumeName[i])) - { - i--; - } - if (isspace(VolumeName[i+1])) - VolumeName[i+1] = '\0'; - - return VolumeName; -#endif } //---------------------------------------------------------------------------- @@ -974,10 +689,8 @@ bool c3files_FindCDByName(MBCHAR const * name) for (DriveIdType i = DRIVE_FIRST; (i <= DRIVE_LAST) && !g_hasCD; ++i) { -#if defined(WIN32) // #ifndef USE_SDL if (IsCD[static_cast(i - DRIVE_FIRST)]) { -#endif MBCHAR const * cdName = c3files_GetVolumeName(i); if (cdName) @@ -991,12 +704,12 @@ bool c3files_FindCDByName(MBCHAR const * name) g_hasCD = true; } } -#if defined(WIN32) // #ifndef USE_SDL } -#endif } return g_hasCD || !g_theProfileDB->IsRequireCD(); } } // local namespace + +#endif // USE_SDL diff --git a/ctp2_code/ctp/ctp2_utils/c3files.h b/ctp2_code/ctp/ctp2_utils/c3files.h index f21a07e1c..18bf24863 100644 --- a/ctp2_code/ctp/ctp2_utils/c3files.h +++ b/ctp2_code/ctp/ctp2_utils/c3files.h @@ -25,7 +25,7 @@ // // Modifications from the original Activision code: // -// - c3files_fopen can now ignore scenario paths. (9-Apr-2007 Martin Gühmann) +// - c3files_fopen can now ignore scenario paths. (9-Apr-2007 Martin G�hmann) // //---------------------------------------------------------------------------- @@ -84,8 +84,6 @@ enum C3SAVEDIR { // WIN32_FIND_DATA is native type typedef MBCHAR DriveIdType; -// TODO: remove when all references have been removed -#define c3files_GetCTPCDDriveLetter c3files_GetCtpCdId #else @@ -153,22 +151,11 @@ bool c3files_getfilelist_ex(C3SAVEDIR dirID, MBCHAR *ext, PointerList -#if defined(WIN32) #include "windows.h" #include "mbstring.h" #include "mmsystem.h" -#elif defined(LINUX) -#include -#include -#include -#include -#endif + #if defined(HAVE_UNISTD_H) #include #endif -#if defined(USE_SDL) -#include -#endif #include "cheatkey.h" #include "tracklen.h" @@ -84,11 +77,9 @@ char *tracklen_cryptAscii(char *s) static void DMCIError(int error) { -#ifdef WIN32 char szScratch[ MAX_PATH ]; mciGetErrorString( error, szScratch, MAX_PATH ); tracklen_DPRINT((tracklen_buf, "last MCI error = %s\n", szScratch )); -#endif } #else @@ -108,22 +99,13 @@ void tracklen_cryptBinary(char *data, size_t len) data[ index ] ^= p[ index % 400 ]; } -#ifdef USE_SDL -static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, SDL_CD *cdrom ) -#else static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, unsigned int wDeviceID ) -#endif { -#if defined(WIN32) && !defined(USE_SDL) MCI_STATUS_PARMS msp; MCI_SET_PARMS mp; long totalLen_ms = 0; -#else - uint64 totalLen_ms = 0; -#endif DWORD i; -#if defined(WIN32) && !defined(USE_SDL) memset(&mp, 0, sizeof(mp)); mp.dwTimeFormat = MCI_FORMAT_MILLISECONDS; if (mciSendCommand(wDeviceID, MCI_SET, MCI_SET_TIME_FORMAT, (DWORD_PTR)&mp)) @@ -142,15 +124,6 @@ static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, unsigned int w return __LINE__; } trackLenBuf[0] = msp.dwReturn; -#elif defined(USE_SDL) - if (!cdrom) - return __LINE__; - if (!CD_INDRIVE(SDL_CDStatus(cdrom))) - { - return __LINE__; - } - trackLenBuf[0] = cdrom->numtracks; -#endif tracklen_DPRINT((tracklen_buf, "GetTrackLengths: %d tracks\n", trackLenBuf[0])); if (trackLenBuf[0] > tracklen_MAXTRACKS) { tracklen_DPRINT((tracklen_buf, "GetTrackLengths: too many tracks\n")); @@ -158,7 +131,6 @@ static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, unsigned int w } for (i = 1; i <= trackLenBuf[0]; i++) { -#if defined(WIN32) && !defined(USE_SDL) memset(&msp, 0, sizeof(msp)); msp.dwItem = MCI_STATUS_LENGTH; msp.dwTrack = i; @@ -170,18 +142,8 @@ static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, unsigned int w continue; } trackLenBuf[i] = msp.dwReturn; -#elif defined(USE_SDL) - uint64 ui = cdrom->track[i - 1].length * 1000 / CD_FPS; - // FIXME: This may not be reusable - // ALL tracks on CTP2 CD are one ms shorter due to rounding - trackLenBuf[i] = ++ui; - totalLen_ms += cdrom->track[i - 1].length * 1000; -#endif tracklen_DPRINT((tracklen_buf, "GetTrackLengths: track %d len %d\n", i, trackLenBuf[i])); } -#if defined(USE_SDL) - totalLen_ms = totalLen_ms / CD_FPS + 1; -#elif defined(WIN32) msp.dwItem = MCI_STATUS_LENGTH; if(mciSendCommand(wDeviceID, MCI_STATUS, MCI_STATUS_ITEM, (DWORD_PTR)&msp)) { @@ -190,7 +152,6 @@ static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, unsigned int w return __LINE__; } totalLen_ms = msp.dwReturn; -#endif tracklen_DPRINT((tracklen_buf, "GetTrackLengths: got disc len %d\n", totalLen_ms )); if (totalLen_ms < ((74 * 60 + 30) * 1000)) { @@ -204,30 +165,16 @@ static int tracklen_GetTrackLengthsViaHandle( DWORD *trackLenBuf, unsigned int w return 0; } -#if defined(USE_SDL) -int tracklen_GetTrackLengths(DWORD *trackLenBuf, int iDrive) -#else + int tracklen_GetTrackLengths(DWORD *trackLenBuf, char whichDrive) -#endif { -#if defined(USE_SDL) - const char *driveName = SDL_CDName(iDrive); - if (!driveName) - return __LINE__; -#endif -#if defined(WIN32) -#if defined(USE_SDL) - char whichDrive = driveName[0]; -#endif MCI_OPEN_PARMS mop; char szDrive[16]; -#endif #ifdef tracklen_LOGGING if (!tracklen_fp) tracklen_fp = fopen(tracklen_LOGFILE, "w"); #endif -#if defined(WIN32) && !defined(USE_SDL) memset(&mop, 0, sizeof(mop)); mop.lpstrDeviceType = (LPCSTR)(MCI_DEVTYPE_CD_AUDIO); mop.lpstrAlias = NULL; @@ -240,27 +187,16 @@ int tracklen_GetTrackLengths(DWORD *trackLenBuf, char whichDrive) int iRet = mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_ELEMENT | MCI_OPEN_TYPE | MCI_OPEN_TYPE_ID | MCI_OPEN_SHAREABLE, (DWORD_PTR)&mop); if (iRet) -#elif defined(USE_SDL) - SDL_CD *cdrom = SDL_CDOpen(iDrive); - if (cdrom == NULL) -#endif { tracklen_DPRINT((tracklen_buf, "GetTrackLengths: failed to open cdrom device.\n" )); -#ifndef USE_SDL DMCIError( iRet ); -#endif return __LINE__; } tracklen_DPRINT((tracklen_buf, "GetTrackLengths: Opened cdrom device\n" )); -#ifdef USE_SDL - int iRet = tracklen_GetTrackLengthsViaHandle( trackLenBuf, cdrom ); - SDL_CDClose(cdrom); -#else iRet = tracklen_GetTrackLengthsViaHandle( trackLenBuf, mop.wDeviceID); mciSendCommand( mop.wDeviceID, MCI_CLOSE, 0, NULL ); -#endif tracklen_DPRINT((tracklen_buf, "GetTrackLengths: Returning %d\n", iRet )); return iRet; @@ -274,38 +210,19 @@ static int tracklen_CheckTrackLengths2( DWORD *trackLenBuf) tracklen_DPRINT((tracklen_buf, "CheckTrackLengths2: begin\n" )); int i = 0; -#if defined(WIN32) && !defined(USE_SDL) HWND hCD; for (i = 0; (hCD=FindWindow( "SJE_CdPlayerClass",NULL)) && i < 100; i++) { tracklen_DPRINT((tracklen_buf, "CheckTrackLengths2: Shutting down CD player\n" )); SendMessage( hCD, WM_CLOSE, 0, 0 ); } -#endif int iDrive; -#if defined(USE_SDL) - for (iDrive = 0; iDrive < SDL_CDNumDrives(); iDrive++) { -#else for (iDrive = 0; iDrive < 26; iDrive++) { -#endif -#if defined(USE_SDL) - const char *driveName = SDL_CDName(iDrive); - if (!driveName) - continue; -#endif -#if defined(WIN32) char szDrive[ MAX_PATH ]; int iDriveType; -#if defined(USE_SDL) - if (driveName) - szDrive[0] = driveName[0]; - else - szDrive[0] = ' '; -#else szDrive[0] = static_cast(iDrive + 'A'); -#endif szDrive[1] = ':'; szDrive[2] = '\\'; szDrive[3] = 0; @@ -315,13 +232,8 @@ static int tracklen_CheckTrackLengths2( DWORD *trackLenBuf) continue; } tracklen_DPRINT((tracklen_buf, "CheckTrackLengths2: device %s is cd.\n", szDrive )); -#endif DWORD newbuf[tracklen_MAXTRACKS]; -#if defined(USE_SDL) - int iRet = tracklen_GetTrackLengths(newbuf, iDrive); -#else int iRet = tracklen_GetTrackLengths(newbuf, szDrive[0]); -#endif if (iRet) { tracklen_DPRINT((tracklen_buf, "CheckTrackLengths2: drive %s fails check %d\n", szDrive, iRet )); @@ -358,28 +270,7 @@ DWORD *tracklen_LoadEncryptedKey( DWORD *trackLenBuf, const char *szFile ) char szTemp[MAX_PATH] = {0}; if( !strchr(szFile, ':' ) && strncmp( szFile, FILE_SEP FILE_SEP, 2 ) ) { -#if defined(WIN32) GetModuleFileName( NULL, szTemp, MAX_PATH ); -#elif defined(HAVE_UNISTD_H) && defined(LINUX) - char szLink[MAX_PATH] = { 0 }; - struct stat st = { 0 }; - pid_t pid = getpid(); - if (pid < 0) - return NULL; - - snprintf(szLink, sizeof(szLink) - 1, "/proc/%ld/exe", pid); - int rc = lstat(szLink, &st); - if (rc == -1) - return NULL; - - if (!S_ISLNK(st.st_mode)) - return NULL; - - int size = readlink(szLink, szTemp, sizeof(szTemp)); - if ((size < 0) || (static_cast(size) > sizeof(szTemp))) - return NULL; - szTemp[size] = 0; -#endif char *pos = (char*)strrchr(szTemp, FILE_SEPC); if (pos) { *pos = '\0'; @@ -392,52 +283,22 @@ DWORD *tracklen_LoadEncryptedKey( DWORD *trackLenBuf, const char *szFile ) else strcpy( szTemp, szFile ); -#ifdef WIN32 HANDLE hFile = CreateFile( szTemp, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ); if( hFile == INVALID_HANDLE_VALUE ) { -#else - FILE *f = fopen(szTemp, "r"); - - if (!f) - { - strcpy( szTemp, szFile ); - f = fopen(szTemp, "r"); - } - - if (!f) { -#endif tracklen_DPRINT((tracklen_buf, "tracklen_LoadEncryptedKey: can't open %s\n", szTemp)); return NULL; } -#ifdef WIN32 DWORD dwSize = GetFileSize( hFile, NULL ); -#else - struct stat st = { 0 }; - size_t dwSize = 0; - if (stat(szTemp, &st) == 0) { - dwSize = st.st_size; - } -#endif if ((dwSize < 4) || (dwSize % 4)) { tracklen_DPRINT((tracklen_buf, "tracklen_LoadEncryptedKey: %s bad size\n", szTemp)); -#ifdef WIN32 CloseHandle( hFile ); -#else - fclose(f); -#endif return NULL; } -#ifdef WIN32 DWORD ignore; ReadFile( hFile, trackLenBuf, dwSize, &ignore, NULL ); CloseHandle( hFile ); -#else - size_t ignore; - ignore = fread(trackLenBuf, 1, dwSize, f); - fclose(f); -#endif if( ignore < dwSize ) { tracklen_DPRINT((tracklen_buf, "tracklen_LoadEncryptedKey: file %s bad size 2\n", szTemp)); return NULL; @@ -528,13 +389,10 @@ BYTE tracklen_CheckTrackLengths( char *szVersionInfoBuffer ) #define AUTORUN_DEFAULT 0x95 #define AUTORUN_DISABLE 0xff -#if defined(WIN32) static ULONG s_oldAutoRunValue = AUTORUN_UNKNOWN; -#endif void tracklen_AutoPlay_Disable() { -#if defined(WIN32) int res; HKEY hkey; @@ -553,12 +411,10 @@ void tracklen_AutoPlay_Disable() RegFlushKey(hkey); RegCloseKey(hkey); } -#endif } void tracklen_AutoPlay_Restore() { -#if defined(WIN32) int res; HKEY hkey = NULL; @@ -572,5 +428,6 @@ void tracklen_AutoPlay_Restore() RegFlushKey(hkey); RegCloseKey(hkey); } -#endif } + +#endif // USE_SDL diff --git a/ctp2_code/ctp/ctp2_utils/tracklen.h b/ctp2_code/ctp/ctp2_utils/tracklen.h index dfdf57335..6fa499d69 100644 --- a/ctp2_code/ctp/ctp2_utils/tracklen.h +++ b/ctp2_code/ctp/ctp2_utils/tracklen.h @@ -27,14 +27,13 @@ #ifdef HAVE_PRAGMA_ONCE #pragma once #endif + #ifndef tracklen_h #define tracklen_h -#if defined(WIN32) +#if !defined(USE_SDL) + #include -#else -#include "windows.h" -#endif #ifdef __cplusplus extern "C" { @@ -62,11 +61,7 @@ char *tracklen_cryptAscii(char *s); void tracklen_cryptBinary(char *data, size_t len); DWORD *tracklen_LoadEncryptedKey( DWORD *trackLenBuf, const char *szFile ); -#if defined(WIN32) int tracklen_GetTrackLengths(DWORD *trackLenBuf, char whichDrive); -#else -int tracklen_GetTrackLengths(DWORD *trackLenBuf, int iDrive); -#endif char *GetVersionInfo( DWORD *trackLenBuffer ); BYTE tracklen_CheckTrackLengths( char *szVersionInfoBuffer = NULL ); void tracklen_AutoPlay_Disable(); @@ -76,4 +71,6 @@ void tracklen_AutoPlay_Restore(); } #endif -#endif +#endif // USE_SDL + +#endif // tracklen_h diff --git a/ctp2_code/ctp/debugtools/debugmemory.cpp b/ctp2_code/ctp/debugtools/debugmemory.cpp index a599aa2ea..2b16385cf 100644 --- a/ctp2_code/ctp/debugtools/debugmemory.cpp +++ b/ctp2_code/ctp/debugtools/debugmemory.cpp @@ -435,8 +435,8 @@ const unsigned char FILL_BYTE_FREE = 0x67; const unsigned char FILL_BYTE_MARKER = 0x68; const unsigned char FILL_BYTE_REALLOC = 0x69; -const unsigned char DATA_GUARD_SIZE = 4; -const unsigned char HEADER_GUARD_SIZE = 4; +const unsigned char DATA_GUARD_SIZE = 8; +const unsigned char HEADER_GUARD_SIZE = 8; const int CALL_STACK_SIZE = 60; @@ -1351,4 +1351,4 @@ void operator delete (void *mem) #endif // MEMORY_LOGGED -#endif // _DEBUG +#endif // _DEBUG \ No newline at end of file diff --git a/ctp2_code/ctp/debugtools/debugmemory.h b/ctp2_code/ctp/debugtools/debugmemory.h index f2ebc20ff..8a6c4f053 100644 --- a/ctp2_code/ctp/debugtools/debugmemory.h +++ b/ctp2_code/ctp/debugtools/debugmemory.h @@ -146,6 +146,6 @@ void DebugMemoryHeap_GuardedClose (const char *file, int line, MemoryHeap h } #endif -#endif // __DEBUGMEMORY_H - #endif // _DEBUG + +#endif // __DEBUGMEMORY_H diff --git a/ctp2_code/ctp/debugtools/log.cpp b/ctp2_code/ctp/debugtools/log.cpp index e7d4d9e2e..3b3c9c45f 100644 --- a/ctp2_code/ctp/debugtools/log.cpp +++ b/ctp2_code/ctp/debugtools/log.cpp @@ -19,7 +19,7 @@ #endif #ifdef USE_SDL -#include +#include #endif #ifdef __linux__ diff --git a/ctp2_code/ctp/display.cpp b/ctp2_code/ctp/display.cpp index e6077d651..10b389d2a 100644 --- a/ctp2_code/ctp/display.cpp +++ b/ctp2_code/ctp/display.cpp @@ -9,7 +9,7 @@ #ifdef __AUI_USE_DIRECTX__ #include #elif defined(__AUI_USE_SDL__) -#include +#include #endif PointerList *g_displayModes = NULL; @@ -29,8 +29,6 @@ extern sint32 g_ScreenHeight; extern BOOL g_exclusiveMode; extern BOOL g_createDirectDrawOnSecondary; -extern BOOL g_SDL_flags; - #include "profileDB.h" extern ProfileDB *g_theProfileDB; @@ -138,56 +136,32 @@ void display_EnumerateDisplayModes(void) g_displayModes = new PointerList; #else - SDL_PixelFormat fmt = { 0 }; - fmt.BitsPerPixel = 16; - SDL_Rect **modes = SDL_ListModes(/*&fmt*/NULL, SDL_FULLSCREEN); - g_displayModes = new PointerList; - if (0 == modes) { - return; - } else if ((SDL_Rect **) -1 == modes) { - // Fallback if SDL reports us to support anything, - // we'll pick 800 x 600 and 1024 x 768 - const SDL_VideoInfo *info = SDL_GetVideoInfo(); - if (0 == info) { - return; - } - if (0 == info->vfmt) { - return; - } - if (16 < info->vfmt->BitsPerPixel) { - return; - } - CTPDisplayMode *mode; - mode = new CTPDisplayMode; - if (!mode) - return; - mode->width = 800; - mode->height = 600; - g_displayModes->AddTail(mode); - mode = new CTPDisplayMode; - if (!mode) - return; - mode->width = 1024; - mode->height = 768; - g_displayModes->AddTail(mode); - } else { - for (int i = 0; modes[i]; i++) { - // We might get modes multiple times for each bpp - // supported. Thus, check if we got it already. - if (!display_IsLegalResolution(modes[i]->w, - modes[i]->h) - && (modes[i]->h>=600)) { - CTPDisplayMode *mode = new CTPDisplayMode; - if (!mode) - return; - mode->width = modes[i]->w; - mode->height = modes[i]->h; - g_displayModes->AddTail(mode); - } - } - } + static const int PRIMARY_DISPLAY = 0; + int numberOfDisplayModes = SDL_GetNumDisplayModes(PRIMARY_DISPLAY); + if (numberOfDisplayModes < 1) { + c3errors_FatalDialog("CivApp", "Unable to find display-modes:\n%s\n", SDL_GetError()); + return; + } + + SDL_DisplayMode displayMode; + for (int i = 0; i < numberOfDisplayModes; i++) { + const int rc = SDL_GetDisplayMode(PRIMARY_DISPLAY, i, &displayMode); + if (rc < 0) { + c3errors_FatalDialog("CivApp", "Unable to get display-mode:\n%s\n", SDL_GetError()); + return; + } + if (!display_IsLegalResolution(displayMode.w, displayMode.h) && (displayMode.h >= 600)) { + CTPDisplayMode *mode = new CTPDisplayMode; + if (!mode) { + return; + } + mode->width = displayMode.w; + mode->height = displayMode.h; + g_displayModes->AddTail(mode); + } + } #endif #ifdef __AUI_USE_DIRECTX__ @@ -320,9 +294,6 @@ int display_Initialize(HINSTANCE hInstance, int iCmdShow) #endif display_EnumerateDisplayModes(); - - - BOOL foundRes = FALSE; if (g_theProfileDB->IsTryWindowsResolution()) { diff --git a/ctp2_code/gs/fileio/CivPaths.cpp b/ctp2_code/gs/fileio/CivPaths.cpp index baf595efa..34f728224 100644 --- a/ctp2_code/gs/fileio/CivPaths.cpp +++ b/ctp2_code/gs/fileio/CivPaths.cpp @@ -84,7 +84,9 @@ void CivPaths_CleanupCivPaths() CivPaths::CivPaths(AUI_ERRCODE &errcode) : m_hdPath (new MBCHAR[_MAX_PATH]), +#if !defined(USE_SDL) m_cdPath (new MBCHAR[_MAX_PATH]), +#endif m_defaultPath (new MBCHAR[_MAX_PATH]), m_localizedPath (new MBCHAR[_MAX_PATH]), m_dataPath (new MBCHAR[_MAX_PATH]), @@ -132,7 +134,12 @@ CivPaths::CivPaths(AUI_ERRCODE &errcode) } fscanf(fin, "%s", m_hdPath); +#if defined(USE_SDL) + MBCHAR dummy[_MAX_PATH]; + fscanf(fin, "%s", dummy); +#else // USE_SDL fscanf(fin, "%s", m_cdPath); +#endif // USE_SDL fscanf(fin, "%s", m_defaultPath); fscanf(fin, "%s", m_localizedPath); fscanf(fin, "%s", m_dataPath); @@ -146,7 +153,9 @@ CivPaths::CivPaths(AUI_ERRCODE &errcode) fscanf(fin, "%s", m_saveClipsPath); ReplaceFileSeperator(m_hdPath); +#if !defined(USE_SDL) ReplaceFileSeperator(m_cdPath); +#endif // USE_SDL ReplaceFileSeperator(m_defaultPath); ReplaceFileSeperator(m_localizedPath); ReplaceFileSeperator(m_dataPath); @@ -189,7 +198,9 @@ CivPaths::~CivPaths() delete [] m_curScenarioPath; delete [] m_curScenarioPackPath; delete [] m_hdPath; +#if !defined(USE_SDL) delete [] m_cdPath; +#endif // USE_SDL delete [] m_defaultPath; delete [] m_localizedPath; delete [] m_dataPath; @@ -215,19 +226,20 @@ void CivPaths::CreateSaveFolders(const MBCHAR *path) c3files_CreateDirectory(path); sprintf(subFolderPath, "%s%s%s", path, FILE_SEP, m_saveGamePath); - c3files_CreateDirectory(path); + c3files_CreateDirectory(subFolderPath); sprintf(subFolderPath, "%s%s%s", path, FILE_SEP, m_saveQueuePath); - c3files_CreateDirectory(path); + c3files_CreateDirectory(subFolderPath); sprintf(subFolderPath, "%s%s%s", path, FILE_SEP, m_saveMPPath); - c3files_CreateDirectory(path); + c3files_CreateDirectory(subFolderPath); sprintf(subFolderPath, "%s%s%s", path, FILE_SEP, m_saveSCENPath); - c3files_CreateDirectory(path); + c3files_CreateDirectory(subFolderPath); sprintf(subFolderPath, "%s%s%s", path, FILE_SEP, m_saveMapPath); - c3files_CreateDirectory(path); + c3files_CreateDirectory(subFolderPath); sprintf(subFolderPath, "%s%s%s", path, FILE_SEP, m_saveClipsPath); - c3files_CreateDirectory(path); + c3files_CreateDirectory(subFolderPath); } +#if !defined(USE_SDL) void CivPaths::InitCDPath(void) { MBCHAR tempPath[_MAX_PATH] = {0}; @@ -236,27 +248,10 @@ void CivPaths::InitCDPath(void) if(ctpcd < 0) return; -#if defined(LINUX) - const MBCHAR *mount = c3files_GetCDDriveMount(tempPath, _MAX_PATH, ctpcd); - if(NULL == mount) - return; - - if(!m_cdPath[0]) - { - strcpy(tempPath, m_cdPath); - return; - } - - if(FILE_SEPC == m_cdPath[0]) - return; - - strcat(tempPath, FILE_SEP); - strcat(tempPath, m_cdPath); -#else // WIN32 sprintf(tempPath, "%c:%s%s", ctpcd, FILE_SEP, m_cdPath); -#endif strcpy(m_cdPath, tempPath); } +#endif // USE_SDL MBCHAR *CivPaths::MakeSavePath(MBCHAR *fullPath, MBCHAR *s1, MBCHAR *s2, MBCHAR *s3) { @@ -500,6 +495,7 @@ MBCHAR *CivPaths::FindFile(C3DIR dir, const MBCHAR *filename, MBCHAR *path, return path; } +#if !defined(USE_SDL) // The CD will only have the original content if (checkLocalizedPath && MakeAssetPath(fullPath, m_cdPath, m_dataPath, m_localizedPath, m_assetPaths[dir], filename)) { @@ -512,6 +508,7 @@ MBCHAR *CivPaths::FindFile(C3DIR dir, const MBCHAR *filename, MBCHAR *path, strcpy(path, fullPath); return path; } +#endif // !USE_SDL if (check_prjfile && ((dir == C3DIR_PATTERNS) || @@ -633,6 +630,7 @@ bool CivPaths::FindPath(C3DIR dir, int num, MBCHAR * path) sprintf(tempPath, "%s%s%s%s%s%s%s", m_hdPath, FILE_SEP, m_dataPath, FILE_SEP, m_defaultPath, FILE_SEP, m_assetPaths[dir]); break; +#if !defined(USE_SDL) case 6: if (m_cdPath && m_cdPath[0]) { @@ -647,7 +645,7 @@ bool CivPaths::FindPath(C3DIR dir, int num, MBCHAR * path) m_dataPath, FILE_SEP, m_defaultPath, FILE_SEP, m_assetPaths[dir]); } break; - +#endif // USE_SDL default: return false; } // switch diff --git a/ctp2_code/gs/fileio/CivPaths.h b/ctp2_code/gs/fileio/CivPaths.h index 0844e4557..18f3f2ed2 100644 --- a/ctp2_code/gs/fileio/CivPaths.h +++ b/ctp2_code/gs/fileio/CivPaths.h @@ -43,8 +43,9 @@ class CivPaths { private: MBCHAR *m_hdPath; +#if !defined(USE_SDL) MBCHAR *m_cdPath; - +#endif // USE_SDL MBCHAR *m_defaultPath; MBCHAR *m_localizedPath; @@ -76,7 +77,9 @@ class CivPaths { void CreateSaveFolders(const MBCHAR *path); +#if !defined(USE_SDL) void InitCDPath(void); +#endif MBCHAR *GetSavePath(C3SAVEDIR dir, MBCHAR *path); diff --git a/ctp2_code/gs/fileio/GameFile.cpp b/ctp2_code/gs/fileio/GameFile.cpp index 322e2740c..e2f30c1f6 100644 --- a/ctp2_code/gs/fileio/GameFile.cpp +++ b/ctp2_code/gs/fileio/GameFile.cpp @@ -28,17 +28,17 @@ // - Readded Activision patch new magic number 66. // - Fixed autosave directory name for scenarios to match normal directory. // - Fixed the scenario savegame bug (but not for autosave, that still needs to be done) -// - Replaced old civilisation database by new one. (Aug 20th 2005 Martin Gühmann) -// - Made progress bar more fluently. (Aug 22nd 2005 Martin Gühmann) -// - Removed old sprite state databases. (Aug 29th 2005 Martin Gühmann) -// - Removed old difficulty database. (April 29th 2006 Martin Gühmann) -// - Removed old pollution database. (July 15th 2006 Martin Gühmann) -// - Removed old gobal warming database. (July 15th 2006 Martin Gühmann) -// - Removed old concept database. (31-Mar-2007 Martin Gühmann) -// - Removed old const database. (5-Aug-2007 Martin Gühmann) -// - Replaced CIV_INDEX by sint32. (2-Jan-2008 Martin Gühmann) +// - Replaced old civilisation database by new one. (Aug 20th 2005 Martin Gühmann) +// - Made progress bar more fluently. (Aug 22nd 2005 Martin Gühmann) +// - Removed old sprite state databases. (Aug 29th 2005 Martin Gühmann) +// - Removed old difficulty database. (April 29th 2006 Martin Gühmann) +// - Removed old pollution database. (July 15th 2006 Martin Gühmann) +// - Removed old gobal warming database. (July 15th 2006 Martin Gühmann) +// - Removed old concept database. (31-Mar-2007 Martin Gühmann) +// - Removed old const database. (5-Aug-2007 Martin Gühmann) +// - Replaced CIV_INDEX by sint32. (2-Jan-2008 Martin Gühmann) // - Make the Linux version loading and producing Windows compatible -// savegames. (16-Jan-2019 Martin Gühmann) +// savegames. (16-Jan-2019 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -845,7 +845,7 @@ uint32 GameFile::Restore(const MBCHAR *filepath) g_theProgressWindow->StartCountingTo( 1080 ); - g_civApp->InitializeGame(archive); + g_civApp->InitializeGame(&archive); g_theProgressWindow->StartCountingTo( 1090 ); diff --git a/ctp2_code/gs/utility/gameinit.cpp b/ctp2_code/gs/utility/gameinit.cpp index 44d4e90b1..8c77c5e5a 100644 --- a/ctp2_code/gs/utility/gameinit.cpp +++ b/ctp2_code/gs/utility/gameinit.cpp @@ -29,22 +29,22 @@ // Modifications from the original Activision code: // // - Added player selection for new single player game and scenarios of -// all types, by Martin Gühmann. +// all types, by Martin Gühmann. // - Fixed scenarios that allow players other than player 1 to be played, -// by Martin Gühmann +// by Martin Gühmann // - Added multiplayer to single player game conversion for testing. // - Prevent assigning the same civilisation index twice, while keeping the // human player selection. // - TradePool is fixed on reload if the number of goods in the // savegame differs from the number of goods in the database. -// - June 4th 2005 Martin Gühmann +// - June 4th 2005 Martin Gühmann // - Allowed for nPlayers to be 2 or 3 - JJB 2005/06/28 // - Removed auto-tutorial on low difficulty - JJB 2005/06/28 -// - Removed refferences to the civilisation database. (Aug 20th 2005 Martin Gühmann) -// - Removed unused SpriteStateDB refferences. (Aug 28th 2005 Martin Gühmann) -// - Reused obsolate concept icon database slot for new map icon database. (3-Mar-2007 Martin Gühmann) -// - Removed old concept database. (31-Mar-2007 Martin Gühmann) -// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) +// - Removed refferences to the civilisation database. (Aug 20th 2005 Martin Gühmann) +// - Removed unused SpriteStateDB refferences. (Aug 28th 2005 Martin Gühmann) +// - Reused obsolate concept icon database slot for new map icon database. (3-Mar-2007 Martin Gühmann) +// - Removed old concept database. (31-Mar-2007 Martin Gühmann) +// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -1443,7 +1443,7 @@ sint32 gameinit_GetCivForSlot(sint32 slot) } -sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) +sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive *archive) { g_debugWindow->SetDebugMask(k_DBG_AI); @@ -1470,8 +1470,8 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) // Removed the auto-tutorial on low difficulty, since it causes // more problems than it solves - JJB - if (&archive) { - g_rand = new RandomGenerator(archive); + if (archive) { + g_rand = new RandomGenerator(*archive); } else { #ifdef _DEBUG FILE * fin = fopen ("logs" FILE_SEP "dbgseed.txt", "r"); @@ -1512,8 +1512,8 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) - if(&archive) { - g_theGameSettings = new GameSettings(archive); + if(archive) { + g_theGameSettings = new GameSettings(*archive); } else { g_theGameSettings = new GameSettings(); } @@ -1523,8 +1523,8 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) bool loadEverything = !g_isScenario || (g_startInfoType == STARTINFOTYPE_NOLOCS); - if (&archive) { - g_theWorld = new World(archive) ; + if (archive) { + g_theWorld = new World(*archive) ; if( (g_isScenario && g_startInfoType != STARTINFOTYPE_NOLOCS)) { @@ -1579,8 +1579,8 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) Assert(g_theWorld); - if (&archive && loadEverything){ - g_turn = new TurnCount(archive); + if (archive && loadEverything){ + g_turn = new TurnCount(*archive); } else { g_turn = new TurnCount(); if(g_network.IsActive() || g_network.IsNetworkLaunch()) { @@ -1591,8 +1591,8 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) } } - if (&archive && loadEverything){ - g_selected_item = new SelectedItem(archive); + if (archive && loadEverything){ + g_selected_item = new SelectedItem(*archive); }else { g_selected_item = new SelectedItem(nPlayers); } @@ -1614,23 +1614,23 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) sint16(g_theWorld->GetYHeight()), g_theWorld->IsYwrap()); - if (&archive && loadEverything) - g_theUnitPool = new UnitPool(archive); + if (archive && loadEverything) + g_theUnitPool = new UnitPool(*archive); else g_theUnitPool = new UnitPool(); Assert(g_theUnitPool); - if(&archive && loadEverything) - g_theArmyPool = new ArmyPool(archive); + if(archive && loadEverything) + g_theArmyPool = new ArmyPool(*archive); else g_theArmyPool = new ArmyPool(); Assert(g_theArmyPool); - if(&archive && loadEverything) + if(archive && loadEverything) g_theUnitPool->RebuildQuadTree(); - if(&archive && loadEverything) { - g_theTradePool = new TradePool(archive); + if(archive && loadEverything) { + g_theTradePool = new TradePool(*archive); if(g_numGoods != g_theResourceDB->NumRecords()){ sint32 i; @@ -1648,9 +1648,9 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) g_theTradePool = new TradePool(); // 55 is probably the last save game version for CTP1 - if (&archive && loadEverything && (g_saveFileVersion < 55)) + if (archive && loadEverything && (g_saveFileVersion < 55)) { - g_theTradeOfferPool = new TradeOfferPool(archive); + g_theTradeOfferPool = new TradeOfferPool(*archive); } else { @@ -1658,15 +1658,15 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) } Assert(g_theTradeOfferPool); - if (&archive && loadEverything) - g_thePollution = new Pollution(archive); + if (archive && loadEverything) + g_thePollution = new Pollution(*archive); else g_thePollution = new Pollution(); Assert(g_thePollution); - if (&archive && loadEverything && (g_saveFileVersion < 55)) + if (archive && loadEverything && (g_saveFileVersion < 55)) { - g_theTopTen = new TopTen(archive); + g_theTopTen = new TopTen(*archive); } else { @@ -1676,10 +1676,10 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) SPLASH_STRING("Initializing SLIC Engine..."); - if (&archive) + if (archive) { delete g_slicEngine; - g_slicEngine = new SlicEngine(archive); + g_slicEngine = new SlicEngine(*archive); g_slicEngine->PostSerialize(); } else @@ -1715,15 +1715,15 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) SPLASH_STRING("Initializing Object Pools..."); - if(&archive && loadEverything) - g_theTerrainImprovementPool = new TerrainImprovementPool(archive); + if(archive && loadEverything) + g_theTerrainImprovementPool = new TerrainImprovementPool(*archive); else g_theTerrainImprovementPool = new TerrainImprovementPool(); Assert(g_theTerrainImprovementPool) ; - if (&archive && loadEverything && (g_saveFileVersion < 55)) + if (archive && loadEverything && (g_saveFileVersion < 55)) { - g_theDiplomaticRequestPool = new DiplomaticRequestPool(archive) ; + g_theDiplomaticRequestPool = new DiplomaticRequestPool(*archive) ; } else { @@ -1731,15 +1731,15 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) } Assert(g_theDiplomaticRequestPool) ; - if (&archive && loadEverything) - g_theCivilisationPool = new CivilisationPool(archive) ; + if (archive && loadEverything) + g_theCivilisationPool = new CivilisationPool(*archive) ; else g_theCivilisationPool = new CivilisationPool() ; Assert(g_theCivilisationPool) ; - if (&archive && loadEverything && (g_saveFileVersion < 55)) + if (archive && loadEverything && (g_saveFileVersion < 55)) { - g_theAgreementPool = new AgreementPool(archive) ; + g_theAgreementPool = new AgreementPool(*archive) ; } else { @@ -1748,8 +1748,8 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) Assert(g_theAgreementPool) ; delete g_theMessagePool; - if (&archive && loadEverything) - g_theMessagePool = new MessagePool(archive) ; + if (archive && loadEverything) + g_theMessagePool = new MessagePool(*archive) ; else g_theMessagePool = new MessagePool() ; Assert(g_theMessagePool) ; @@ -1758,68 +1758,68 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) g_theCriticalMessagesPrefs = new CriticalMessagesPrefs() ; Assert(g_theCriticalMessagesPrefs) ; - if(&archive && loadEverything) - g_theInstallationPool = new InstallationPool(archive); + if(archive && loadEverything) + g_theInstallationPool = new InstallationPool(*archive); else g_theInstallationPool = new InstallationPool(); Assert(g_theInstallationPool) ; g_theInstallationPool->RebuildQuadTree(); - if (&archive && loadEverything && (g_saveFileVersion < 55)) + if (archive && loadEverything && (g_saveFileVersion < 55)) { sint32 wormholeExists; - archive >> wormholeExists; - g_wormhole = (wormholeExists) ? new Wormhole(archive) : NULL; + *archive >> wormholeExists; + g_wormhole = (wormholeExists) ? new Wormhole(*archive) : NULL; } else { g_wormhole = NULL; } - if(&archive && loadEverything) { - g_theWonderTracker = new WonderTracker(archive); + if(archive && loadEverything) { + g_theWonderTracker = new WonderTracker(*archive); } else { g_theWonderTracker = new WonderTracker(); } - if(&archive && loadEverything && (g_saveFileVersion < 55)) + if(archive && loadEverything && (g_saveFileVersion < 55)) { - g_theAchievementTracker = new AchievementTracker(archive); + g_theAchievementTracker = new AchievementTracker(*archive); } else { g_theAchievementTracker = new AchievementTracker(); } - if (&archive) + if (archive) { delete g_exclusions; - g_exclusions = new Exclusions(archive); + g_exclusions = new Exclusions(*archive); } else { // Exclusions not used } - if(&archive && loadEverything) { - g_featTracker = new FeatTracker(archive); + if(archive && loadEverything) { + g_featTracker = new FeatTracker(*archive); } else { g_featTracker = new FeatTracker; } - if(&archive && loadEverything && (g_saveFileVersion < 55)) + if(archive && loadEverything && (g_saveFileVersion < 55)) { - g_theTradeBids = new TradeBids(archive); + g_theTradeBids = new TradeBids(*archive); } else { g_theTradeBids = new TradeBids; } - if(&archive && loadEverything) + if(archive && loadEverything) { - g_eventTracker = new EventTracker(archive); + g_eventTracker = new EventTracker(*archive); } else { @@ -1838,24 +1838,24 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) sint32 numPlayersLoaded = 0; sint32 i, j; - if (&archive) + if (archive) { for (i = 0; i < k_MAX_PLAYERS; i++) { - archive >> playerAlive; + *archive >> playerAlive; if (playerAlive) { - g_player[i] = new Player(archive); + g_player[i] = new Player(*archive); numPlayersLoaded++; } } sint32 num; - archive >> num; + *archive >> num; for (i = 0; i < num; i++) { - g_deadPlayer->AddTail(new Player(archive)); + g_deadPlayer->AddTail(new Player(*archive)); } if (g_isScenario && g_startInfoType != STARTINFOTYPE_NOLOCS) @@ -1969,7 +1969,7 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) case STARTINFOTYPE_CIVSFIXED: case STARTINFOTYPE_POSITIONSFIXED: -// Added by Martin Gühmann +// Added by Martin Gühmann // No difference between STARTINFOTYPE_CIVSFIXED and STARTINFOTYPE_POSITIONSFIXED { Assert(numPlayersLoaded == 0); @@ -2151,13 +2151,13 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) roboinit_Initalize(archive); CtpAi::Cleanup(); - if (&archive && loadEverything) + if (archive && loadEverything) { g_theWorld->SetAllMoveCost(); g_theWorld->A_star_heuristic->Update(); SPLASH_STRING("Load AI data elements..."); - CtpAi::Load(archive); + CtpAi::Load(*archive); createRobotInterface = false; if(!g_theProfileDB->IsAIOn()) { @@ -2210,7 +2210,7 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) g_theTradeOfferPool->ReRegisterOffers(); - if (!(&archive)) + if (!archive) { sint32 numPlaced = 0; #ifdef _DEBUG @@ -2277,7 +2277,7 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) g_director->AddCopyVision(); } - if(&archive) + if(archive) { SPLASH_STRING("Set all move costs..."); g_theWorld->SetAllMoveCost(); @@ -2382,7 +2382,7 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) } SPLASH_STRING("Reset vision..."); - if(&archive && loadEverything) { + if(archive && loadEverything) { for(i = 0; i < k_MAX_PLAYERS; i++) { if(g_player[i]) { g_player[i]->ResetVision(); @@ -2430,7 +2430,7 @@ sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive) g_scenarioUsePlayerNumber = 0; } - if (!(&archive) || g_isScenario) + if (!archive || g_isScenario) { if (g_startHotseatGame || g_startEmailGame) { diff --git a/ctp2_code/gs/utility/gameinit.h b/ctp2_code/gs/utility/gameinit.h index 76fe70038..e5d35c82b 100644 --- a/ctp2_code/gs/utility/gameinit.h +++ b/ctp2_code/gs/utility/gameinit.h @@ -13,7 +13,7 @@ struct HotseatPlayerSetup; #include "MapPoint.h" // MapPoint sint32 gameinit_InitializeGameFiles(void); -sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive &archive); +sint32 gameinit_Initialize(sint32 mWidth, sint32 mHeight, CivArchive *archive); void gameinit_CleanupMessages(void); void gameinit_Cleanup(void); sint32 gameinit_ResetForNetwork(); diff --git a/ctp2_code/meson.build b/ctp2_code/meson.build index 1de9cea84..3811d5b0c 100644 --- a/ctp2_code/meson.build +++ b/ctp2_code/meson.build @@ -39,16 +39,12 @@ if not win32 tiff = dependency('libtiff-4') zlib = dependency('zlib') - gtk = dependency('gtk+-3.0') - conf.set('USE_GTK', 1) - x11 = dependency('x11', required: false) if x11.found() conf.set('HAVE_X11', 1, description : 'System with X11 present') endif - main_dependencies += [tiff, zlib, gtk, sdl, x11] + main_dependencies += [tiff, zlib, sdl, x11] - main_dependencies += declare_dependency( sources : 'os/nowin32/nowin32.cpp', dependencies : gtk ) incdir += include_directories('os/nowin32') conf.set_quoted('FILE_SEP', '/') diff --git a/ctp2_code/net/io/net_thread.cpp b/ctp2_code/net/io/net_thread.cpp index f1ee9f123..22f2229f5 100644 --- a/ctp2_code/net/io/net_thread.cpp +++ b/ctp2_code/net/io/net_thread.cpp @@ -203,7 +203,7 @@ NET_ERR NetThread::Init(NetIOResponse *response) NetIO::Init(response); #ifdef USE_SDL - if ((m_thread = SDL_CreateThread(NetThread_StartThread, this)) == NULL) { + if ((m_thread = SDL_CreateThread(NetThread_StartThread, "Net-start-thread", this)) == NULL) { #elif defined(WIN32) if((m_threadHandle = CreateThread(NULL, 0, diff --git a/ctp2_code/net/io/net_thread.h b/ctp2_code/net/io/net_thread.h index eac59c5fc..21a832057 100644 --- a/ctp2_code/net/io/net_thread.h +++ b/ctp2_code/net/io/net_thread.h @@ -10,8 +10,8 @@ #include "pointerlist.h" #include "net_anet.h" #ifdef USE_SDL -#include -#include +#include +#include #endif #define k_MAX_NETWORK_PLAYERS 32 diff --git a/ctp2_code/os/autoconf/Makefile.common b/ctp2_code/os/autoconf/Makefile.common index 91eb7f2fd..3c205c6e8 100644 --- a/ctp2_code/os/autoconf/Makefile.common +++ b/ctp2_code/os/autoconf/Makefile.common @@ -6,14 +6,12 @@ CTP2_LDFLAGS = \ $(DIRECTX_LDFLAGS) \ $(DXMEDIA_LDFLAGS) \ $(SDL_LDFLAGS) \ - -ltiff -lz -lSDL -lSDL_image -lSDL_mixer $(SDL_FFMPEG_LDFLAGS) -ldl -lpthread \ + -ltiff -lz -lSDL2 -lSDL2_image -lSDL2_mixer $(SDL_FFMPEG_LDFLAGS) -ldl -lpthread \ $(X_PRE_LIBS) \ - $(X_LIBS) -lX11 \ - $(GTK_LIBS) -ldl + $(X_LIBS) -lX11 -ldl CTP2_CFLAGS=\ $(SDL_CFLAGS) \ - $(GTK_CFLAGS) \ $(X_CFLAGS) CTP2_CXXFLAGS=\ diff --git a/ctp2_code/os/autoconf/sdl_ffmpeg.m4 b/ctp2_code/os/autoconf/sdl_ffmpeg.m4 index 3a71a5eef..5491a0394 100644 --- a/ctp2_code/os/autoconf/sdl_ffmpeg.m4 +++ b/ctp2_code/os/autoconf/sdl_ffmpeg.m4 @@ -3,9 +3,11 @@ dnl $Id$ dnl AC_DEFUN([AM_PATH_SDL_FFMPEG],[ - AC_CHECK_HEADER([SDL/SDL_ffmpeg.h],[ac_found_header=yes],[ac_found_header=no]) - if test x$ac_found_header = xyes; then - SDL_FFMPEG_LDFLAGS="-lSDL_ffmpeg -lavcodec" + AC_CHECK_HEADER([libavcodec/avcodec.h],[av_codec_found_header=yes],[av_codec_found_header=no]) + AC_CHECK_HEADER([libavformat/avformat.h],[av_format_found_header=yes],[av_format_found_header=no]) + AC_CHECK_HEADER([libswscale/swscale.h],[sw_scale_found_header=yes],[sw_scale_found_header=no]) + if test "x$av_codec_found_header" = xyes -a "x$av_format_found_header" = xyes -a "x$sw_scale_found_header" = xyes; then + SDL_FFMPEG_LDFLAGS="-lavutil -lavformat -lavcodec -lswscale -lswresample" AC_DEFINE(USE_SDL_FFMPEG,1,[Enable SDL_ffmpeg library]) else SDL_FFMPEG_LDFLAGS="" diff --git a/ctp2_code/os/nowin32/nowin32.cpp b/ctp2_code/os/nowin32/nowin32.cpp index 582469c1a..e709be3ce 100644 --- a/ctp2_code/os/nowin32/nowin32.cpp +++ b/ctp2_code/os/nowin32/nowin32.cpp @@ -16,12 +16,12 @@ #endif #include #include -#include +#include #include "windows.h" -#ifdef USE_GTK -#include +#ifdef USE_SDL + #include "SDL2/SDL.h" #endif // @ToDo: _fullpath is the version of ptitSeb's branch, check whether there @@ -45,7 +45,8 @@ char* _fullpath(char* absolute, const char* relative, size_t bufsize) else { #ifdef __USE_GNU - char *abs = canonicalize_file_name(CI_FixName(relative)); + const char *fixedName = CI_FixName(relative); + char *abs = canonicalize_file_name(fixedName); if(abs) { strncpy(dest, abs, size - 1); @@ -54,7 +55,29 @@ char* _fullpath(char* absolute, const char* relative, size_t bufsize) } else { - return NULL; + // NOTE: canonicalize_file_name will return NULL if last element does not exist + // as this method should not return NULL in that case we test dirname on existence + char *fixedNameDuplicate = strdup(fixedName); + abs = canonicalize_file_name(dirname(fixedNameDuplicate)); + free(fixedNameDuplicate); + if (abs) + { + strncpy(dest, abs, size - 1); + dest[size - 1] = '\0'; + free(abs); + + // add basename + int spaceLeft = size - strlen(dest); + Assert(spaceLeft >= 0); + strncat(dest, FILE_SEP, spaceLeft); + fixedNameDuplicate = strdup(fixedName); + strncat(dest, basename(fixedNameDuplicate), spaceLeft - strlen(FILE_SEP)); + free(fixedNameDuplicate); + } + else + { + return NULL; + } } #elif defined(BSD) || defined(__USE_BSD) char rlpath[PATH_MAX] = {0}; @@ -118,89 +141,121 @@ uint32 GetTickCount() return SDL_GetTicks(); } -namespace { - int mbRetVal = 0; -} - sint32 MessageBox(HWND parent, const CHAR* msg, const CHAR* title, sint32 flags) { fprintf(stderr, "Messagebox(%s): %s\n", (title ? title : "null"), (msg ? msg : "null")); -#ifdef USE_GTK - GtkWidget *dialog = gtk_message_dialog_new - ( - NULL, - GTK_DIALOG_DESTROY_WITH_PARENT, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_NONE, - msg - ); - gtk_window_set_title(GTK_WINDOW(dialog), title); - - if (flags & MB_OK) - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - GTK_STOCK_OK, IDOK, - NULL); - } - else if(flags & MB_OKCANCEL) - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - GTK_STOCK_OK, IDOK, - GTK_STOCK_CANCEL, IDCANCEL, - NULL); - } - else if(flags & MB_ABORTRETRYIGNORE) - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - "_Abort", IDABORT, - "_Retry", IDRETRY, - "_Ignore", IDIGNORE, - NULL); - } - else if(flags & MB_YESNOCANCEL) - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - GTK_STOCK_YES, IDYES, - GTK_STOCK_NO, IDNO, - GTK_STOCK_CANCEL, IDCANCEL, - NULL); - } - else if(flags & MB_YESNO) - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - GTK_STOCK_YES, IDYES, - GTK_STOCK_NO, IDNO, - NULL); - } - else if(flags & MB_RETRYCANCEL) - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - "_Retry", IDRETRY, - GTK_STOCK_CANCEL, IDCANCEL, - NULL); - } - else if(flags & MB_CANCELTRYCONTINUE) - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - GTK_STOCK_CANCEL, IDCANCEL, - "_Try", IDTRYAGAIN, - "_Continue", IDCONTINUE, - NULL); - } - else - { - gtk_dialog_add_buttons(GTK_DIALOG(dialog), - GTK_STOCK_OK, IDOK, - NULL); +#ifdef USE_SDL + SDL_MessageBoxData data; + + const SDL_MessageBoxColorScheme colorScheme = { + { + // background + { 0xDE, 0xD2, 0xB4 }, + // text + { 0x32, 0x31, 0x32 }, + // button border + { 0x02, 0x02, 0x02 }, + // button background + { 0xE6, 0xDa, 0xC5 }, + // button text + { 0x02, 0x02, 0x02 } + } + }; + + const int MAXIMUM_NUMBER_OF_BUTTONS = 3; + SDL_MessageBoxButtonData buttonData[MAXIMUM_NUMBER_OF_BUTTONS]; + memset(buttonData, 0, sizeof(SDL_MessageBoxButtonData)*MAXIMUM_NUMBER_OF_BUTTONS); + // filter button + switch (flags & 7) { + case MB_OK: + case MB_OKCANCEL: + data.numbuttons = 1; + buttonData[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + buttonData[0].buttonid = IDOK; + buttonData[0].text = "OK"; + if (flags == MB_OKCANCEL) { + data.numbuttons = 2; + buttonData[1].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttonData[1].buttonid = IDCANCEL; + buttonData[1].text = "Cancel"; + } + break; + + case MB_ABORTRETRYIGNORE: + data.numbuttons = 3; + buttonData[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + buttonData[0].buttonid = IDABORT; + buttonData[0].text = "Abort"; + buttonData[1].flags = 0; + buttonData[1].buttonid = IDRETRY; + buttonData[1].text = "Retry"; + buttonData[2].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttonData[2].buttonid = IDIGNORE; + buttonData[2].text = "Ignore"; + break; + + case MB_YESNO: + case MB_YESNOCANCEL: + data.numbuttons = 2; + buttonData[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + buttonData[0].buttonid = IDYES; + buttonData[0].text = "Yes"; + buttonData[1].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttonData[1].buttonid = IDNO; + buttonData[1].text = "No"; + if (flags == MB_YESNOCANCEL) { + data.numbuttons = 3; + buttonData[1].flags = 0; + buttonData[2].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttonData[2].buttonid = IDCANCEL; + buttonData[2].text = "Cancel"; + } + break; + + case MB_RETRYCANCEL: + data.numbuttons = 2; + buttonData[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + buttonData[0].buttonid = IDRETRY; + buttonData[0].text = "Retry"; + buttonData[1].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttonData[1].buttonid = IDCANCEL; + buttonData[1].text = "Cancel"; + break; + + case MB_CANCELTRYCONTINUE: + data.numbuttons = 3; + buttonData[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + buttonData[0].buttonid = IDCONTINUE; + buttonData[0].text = "Continue"; + buttonData[1].flags = 0; + buttonData[1].buttonid = IDTRYAGAIN; + buttonData[1].text = "Try"; + buttonData[2].flags = SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT; + buttonData[2].buttonid = IDCANCEL; + buttonData[2].text = "Cancel"; + break; + + default: + data.numbuttons = 1; + buttonData[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT; + buttonData[0].buttonid = IDOK; + buttonData[0].text = "OK"; + break; } - sint32 result = gtk_dialog_run(GTK_DIALOG(dialog)); - gtk_widget_destroy(dialog); - - while(g_main_iteration(FALSE)) - gtk_main_quit(); + data.buttons = buttonData; + data.flags = SDL_MESSAGEBOX_ERROR; + data.title = title ? title : "null"; + data.message = msg; + data.colorScheme = &colorScheme; + data.window = NULL; - return result; + int selectedButton = IDFAIL; + SDL_ShowMessageBox(&data, &selectedButton); + if (selectedButton == -1) { + selectedButton = buttonData[0].buttonid; + } + return selectedButton; #else return IDFAIL; #endif diff --git a/ctp2_code/robot/utility/RoboInit.h b/ctp2_code/robot/utility/RoboInit.h index e2e2613fc..f2d8fe98d 100644 --- a/ctp2_code/robot/utility/RoboInit.h +++ b/ctp2_code/robot/utility/RoboInit.h @@ -6,7 +6,7 @@ #include "civarchive.h" -extern void roboinit_Initalize(CivArchive &a); +extern void roboinit_Initalize(CivArchive *a); extern void roboinit_Cleanup(); #endif diff --git a/ctp2_code/robot/utility/roboinit.cpp b/ctp2_code/robot/utility/roboinit.cpp index 8c95ac036..c5044e6ea 100644 --- a/ctp2_code/robot/utility/roboinit.cpp +++ b/ctp2_code/robot/utility/roboinit.cpp @@ -38,7 +38,7 @@ UnitAstar * g_theUnitAstar = NULL; -void roboinit_Initalize(CivArchive &a) +void roboinit_Initalize(CivArchive *a) { Astar_Init(); diff --git a/ctp2_code/sound/civsound.cpp b/ctp2_code/sound/civsound.cpp index 1f49363ff..773238789 100644 --- a/ctp2_code/sound/civsound.cpp +++ b/ctp2_code/sound/civsound.cpp @@ -43,7 +43,7 @@ #include "prjfile.h" #if defined(USE_SDL) -#include +#include #endif extern ProjectFile *g_SoundPF; diff --git a/ctp2_code/sound/civsound.h b/ctp2_code/sound/civsound.h index 7c13bb042..c50d65acb 100644 --- a/ctp2_code/sound/civsound.h +++ b/ctp2_code/sound/civsound.h @@ -49,7 +49,7 @@ #endif #if defined(USE_SDL) -#include +#include #else #include "mss.h" #endif diff --git a/ctp2_code/sound/soundmanager.cpp b/ctp2_code/sound/soundmanager.cpp index fe1b89e7d..588b87719 100755 --- a/ctp2_code/sound/soundmanager.cpp +++ b/ctp2_code/sound/soundmanager.cpp @@ -34,7 +34,7 @@ // - #pragmas commented out // - Includes fixed for case sensitive filesystems // - Added sdl sound and cdrom support -// - Initialized local variables. (Sep 9th 2005 Martin G�hmann) +// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -59,12 +59,12 @@ SoundManager *g_soundManager = NULL; namespace { - uint32 const k_CHECK_CD_PERIOD = 4000; // [ms] + uint32 const k_CHECK_MUSIC_PERIOD = 4000; // [ms] uint32 const SLIDER_FULL = 10; #if !defined(USE_SDL) S32 s_masterVolume; -#endif +#endif // USE_SDL sint32 s_startTrack = 1; // skip CD data track } @@ -82,33 +82,31 @@ void SoundManager::Cleanup() SoundManager::SoundManager() : - m_sfxSounds (NULL), - m_voiceSounds (NULL), - m_soundWalker (NULL), - m_sfxVolume (SLIDER_FULL), - m_musicVolume (SLIDER_FULL), - m_voiceVolume (SLIDER_FULL), - m_oldRedbookVolume (0), - m_noSound (false), - m_usePlaySound (false), -#if !defined(USE_SDL) - m_redbook (0), -#else - m_cdrom (0), - m_useOggTracks (false), - m_oggTrack (0), - m_SDLInitFlags (SDL_INIT_NOPARACHUTE), -#endif - m_timeToCheckCD (0), - m_numTracks (0), - m_curTrack (0), - m_lastTrack (0), - m_musicEnabled (false), - m_style (MUSICSTYLE_PLAYLIST), - m_playListPosition (0), - m_userTrack (0), - m_autoRepeat (true), - m_stopRedbookTemporarily (false) + m_sfxSounds (NULL), + m_voiceSounds (NULL), + m_soundWalker (NULL), + m_sfxVolume (SLIDER_FULL), + m_musicVolume (SLIDER_FULL), + m_voiceVolume (SLIDER_FULL), + m_oldRedbookVolume (0), + m_noSound (false), + m_usePlaySound (false), +#if defined(USE_SDL) + m_useOggTracks (false), + m_oggTrack (0), +#else // USE_SDL + m_redbook (0), +#endif // USE_SDL + m_timeToCheckMusic (0), + m_numTracks (0), + m_curTrack (0), + m_lastTrack (0), + m_musicEnabled (false), + m_style (MUSICSTYLE_PLAYLIST), + m_playListPosition (0), + m_userTrack (0), + m_autoRepeat (true), + m_stopRedbookTemporarily (false) { if (g_theProfileDB) { @@ -117,11 +115,6 @@ SoundManager::SoundManager() m_musicVolume = static_cast(g_theProfileDB->GetMusicVolume()); } -#if defined(USE_SDL) && defined(_DEBUG) - // Do not remove this or debugging won't work... :( - m_SDLInitFlags |= SDL_INIT_NOPARACHUTE; -#endif - m_sfxSounds = new PointerList; m_voiceSounds = new PointerList; m_soundWalker = new PointerList::Walker; @@ -157,7 +150,7 @@ void SoundManager::InitSoundDriver() int output_rate = 22050; // 22khz @ 16 Bit stereo Uint16 output_format = AUDIO_S16SYS; int output_channels = 2; - int errcode = SDL_Init(SDL_INIT_AUDIO | m_SDLInitFlags); + int errcode = SDL_InitSubSystem(SDL_INIT_AUDIO); if (errcode < 0) { @@ -165,7 +158,7 @@ void SoundManager::InitSoundDriver() } else { - errcode = Mix_OpenAudio(output_rate, output_format, output_channels, 8192); + errcode = Mix_OpenAudio(output_rate, output_format, output_channels, 256); if (errcode < 0) { // char *err = SDL_GetError(); cerr << "Opening mixer failed:" << err << endl; @@ -173,16 +166,15 @@ void SoundManager::InitSoundDriver() } m_noSound = (errcode < 0); -#else // !USE_SDL +#else // USE_SDL S32 use_digital = 1; S32 use_MIDI = 0; S32 output_rate = 22050; // 22khz @ 16 Bit stereo S32 output_bits = 16; S32 output_channels = 2; - m_noSound = !AIL_quick_startup - (use_digital, use_MIDI, output_rate, output_bits, output_channels); -#endif // defined(USE_SDL) + m_noSound = !AIL_quick_startup(use_digital, use_MIDI, output_rate, output_bits, output_channels); +#endif // USE_SDL InitRedbook(); @@ -202,8 +194,8 @@ void SoundManager::CleanupSoundDriver() Mix_CloseAudio(); } - // SDL_Quit() -> civ_main.cpp:AtExitProc() -#else // !USE_SDL + SDL_QuitSubSystem(SDL_INIT_AUDIO); +#else // USE_SDL AIL_quick_shutdown(); #endif // USE_SDL } @@ -216,48 +208,10 @@ void SoundManager::InitRedbook() if( !m_useOggTracks) { if(CI_FileExists("music/Track02.ogg")) { m_useOggTracks = true; - printf("Detected Ogg Music track, using that instead of CD Audio\n"); + printf("Detected Ogg Music track\n"); } } - if (!m_cdrom && !m_useOggTracks) { - int errcode = SDL_Init(SDL_INIT_CDROM | m_SDLInitFlags); - - Assert(0 == errcode); - if (errcode < 0) { - return; - } - - int numDrives = SDL_CDNumDrives(); - Assert(numDrives >= 0); - - int drive = -1; - int i = 0; - // Hack: We don't have the num of the SDL drive stored, - // so we search for the drive with the drive letter stored - MBCHAR driveLetter = toupper(c3files_GetCtpCdId()); - while ((i < numDrives) && (-1 == drive)) { - const char *cd_name = SDL_CDName(i); - if (cd_name) { - if (toupper(cd_name[0]) == driveLetter) { - drive = i; - } - } - i++; - } - - // No drive match?! - if (drive < 0) { - return; - } - m_cdrom = SDL_CDOpen(drive); - Assert(m_cdrom != 0); - // No control structur? - if (m_cdrom) - { - CDstatus status = SDL_CDStatus(m_cdrom); - } - } -#else // !USE_SDL +#else // USE_SDL if (!m_redbook) { m_redbook = AIL_redbook_open_drive(c3files_GetCtpCdId()); @@ -272,17 +226,13 @@ void SoundManager::CleanupRedbook() Mix_FreeMusic(m_oggTrack); m_oggTrack = NULL; } - if (m_cdrom) { - SDL_CDClose(m_cdrom); - m_cdrom = 0; - } -#else +#else // USE_SDL if (m_redbook) { AIL_redbook_stop(m_redbook); AIL_redbook_close(m_redbook); m_redbook = NULL; } -#endif +#endif // USE_SDL } void SoundManager::ProcessRedbook() @@ -291,51 +241,28 @@ void SoundManager::ProcessRedbook() if (!m_musicEnabled) return; - if (GetTickCount() > m_timeToCheckCD) { + if (GetTickCount() > m_timeToCheckMusic) { + #if defined(USE_SDL) - CDstatus status; if(m_useOggTracks) { if(!Mix_PlayingMusic()) { if (m_curTrack != -1) - PickNextTrack(); + PickNextTrack(); - if (m_curTrack != -1 && !m_stopRedbookTemporarily) - StartMusic(m_curTrack); + if (m_curTrack != -1 && !m_stopRedbookTemporarily) + StartMusic(m_curTrack); } } - if (m_cdrom) { - status = SDL_CDStatus(m_cdrom); -#else +#else // USE_SDL U32 status; if (m_redbook) { status = AIL_redbook_status(m_redbook); -#endif switch (status) { -#if !defined(USE_SDL) case REDBOOK_ERROR: -#else - case CD_TRAYEMPTY: - break; - case CD_ERROR: -#endif - break; -#if !defined(USE_SDL) case REDBOOK_PLAYING: -#else - case CD_PLAYING: -#endif - break; -#if !defined(USE_SDL) case REDBOOK_PAUSED: -#else - case CD_PAUSED: -#endif break; -#if !defined(USE_SDL) case REDBOOK_STOPPED: -#else - case CD_STOPPED: -#endif if (m_curTrack != -1) PickNextTrack(); @@ -344,8 +271,8 @@ void SoundManager::ProcessRedbook() break; } } - - m_timeToCheckCD = GetTickCount() + k_CHECK_CD_PERIOD; +#endif // USE_SDL + m_timeToCheckMusic = GetTickCount() + k_CHECK_MUSIC_PERIOD; } } @@ -369,11 +296,11 @@ void SoundManager::Process(const uint32 &target_milliseconds, if (!sound) continue; if (sound->IsPlaying()) { -#if !defined(USE_SDL) +#if defined(USE_SDL) + if (!Mix_Playing(sound->GetChannel())) { +#else // USE_SDL if (AIL_quick_status(sound->GetHAudio()) == QSTAT_DONE) { -#else - if (!Mix_Playing(sound->GetChannel())) { -#endif +#endif // USE_SDL m_soundWalker->Remove(); delete sound; @@ -393,12 +320,12 @@ void SoundManager::Process(const uint32 &target_milliseconds, if (!sound) continue; if (sound->IsPlaying()) { -#if !defined(USE_SDL) +#if defined(USE_SDL) + if ((-1 == sound->GetChannel()) || + (!Mix_Playing(sound->GetChannel()))) { +#else // USE_SDL if (AIL_quick_status(sound->GetHAudio()) == QSTAT_DONE) { -#else - if ((-1 == sound->GetChannel()) || - (!Mix_Playing(sound->GetChannel()))) { -#endif +#endif // USE_SDL m_soundWalker->Remove(); delete sound; } else { @@ -486,12 +413,12 @@ SoundManager::AddSound(const SOUNDTYPE &type, } else { -#if !defined(USE_SDL) +#if defined(USE_SDL) + int channel = Mix_PlayChannel(-1, sound->GetAudio(), 0); + sound->SetChannel(channel); +#else // USE_SDL AIL_quick_play(sound->GetHAudio(), 1); -#else - int channel = Mix_PlayChannel(-1, sound->GetAudio(), 0); - sound->SetChannel(channel); -#endif +#endif // USE_SDL sound->SetIsPlaying(TRUE); } } @@ -532,12 +459,12 @@ SoundManager::AddLoopingSound(const SOUNDTYPE &type, break; } -#if !defined(USE_SDL) +#if defined(USE_SDL) + int channel = Mix_PlayChannel(-1, sound->GetAudio(), -1); + sound->SetChannel(channel); +#else // USE_SDL AIL_quick_play(sound->GetHAudio(), 0); -#else - int channel = Mix_PlayChannel(-1, sound->GetAudio(), -1); - sound->SetChannel(channel); -#endif +#endif // USE_SDL sound->SetIsLooping(TRUE); sound->SetIsPlaying(TRUE); @@ -551,14 +478,14 @@ SoundManager::TerminateLoopingSound(const SOUNDTYPE &type, if (!existingSound) return; -#if !defined(USE_SDL) - AIL_quick_halt(existingSound->GetHAudio()); +#if defined(USE_SDL) + int channel = existingSound->GetChannel(); + if (channel >= 0) { + Mix_HaltChannel(channel); + } + existingSound->SetChannel(-1); #else - int channel = existingSound->GetChannel(); - if (channel >= 0) { - Mix_HaltChannel(channel); - } - existingSound->SetChannel(-1); + AIL_quick_halt(existingSound->GetHAudio()); #endif } @@ -581,15 +508,15 @@ SoundManager::TerminateAllLoopingSounds(const SOUNDTYPE &type) while (node) { sound = node->GetObj(); if (sound && sound->IsLooping()) { -#if !defined(USE_SDL) +#if defined(USE_SDL) + int channel = sound->GetChannel(); + if (channel >= 0) { + Mix_HaltChannel(channel); + } + sound->SetChannel(-1); +#else // USE_SDL AIL_quick_halt(sound->GetHAudio()); -#else - int channel = sound->GetChannel(); - if (channel >= 0) { - Mix_HaltChannel(channel); - } - sound->SetChannel(-1); -#endif +#endif // USE_SDL } node = node->GetNext(); } @@ -614,14 +541,14 @@ SoundManager::TerminateSounds(const SOUNDTYPE &type) while (node) { sound = node->GetObj(); if (sound) { -#if !defined(USE_SDL) - AIL_quick_halt(sound->GetHAudio()); -#else - int channel = sound->GetChannel(); +#if defined(USE_SDL) + int channel = sound->GetChannel(); if (channel >= 0) { Mix_HaltChannel(channel); } -#endif +#else // USE_SDL + AIL_quick_halt(sound->GetHAudio()); +#endif // USE_SDL } node = node->GetNext(); } @@ -667,11 +594,8 @@ SoundManager::SetVolume(const SOUNDTYPE &type, const uint32 &volume) break; case SOUNDTYPE_MUSIC: m_musicVolume = volume; -#if !defined(USE_SDL) - if (m_redbook) - AIL_redbook_set_volume(m_redbook, (sint32)((double)volume * 12.7)); -#else - if (m_useOggTracks) { +#if defined(USE_SDL) + if (m_useOggTracks) { // Assume max volume is 10... sint32 scaledVolume = (sint32)((double)volume * 12.7); if (scaledVolume > MIX_MAX_VOLUME) { @@ -680,10 +604,10 @@ SoundManager::SetVolume(const SOUNDTYPE &type, const uint32 &volume) Mix_VolumeMusic(scaledVolume); } } - if (m_cdrom) { - // TODO: found nothing in reference - } -#endif +#else // USE_SDL + if (m_redbook) + AIL_redbook_set_volume(m_redbook, (sint32)((double)volume * 12.7)); +#endif // USE_SDL break; } } @@ -868,14 +792,14 @@ SoundManager::SetPosition(const SOUNDTYPE &type, #if defined(USE_SDL) Mix_Chunk * myChunk = sound->GetAudio(); // Why set the volume again? -#else +#else // USE_SDL sint32 panValue = 64; HAUDIO hAudio = sound->GetHAudio(); if (hAudio) { AIL_quick_set_volume(hAudio, volume, panValue); } -#endif +#endif // USE_SDL } node = node->GetNext(); @@ -897,11 +821,11 @@ void SoundManager::StartMusic(const sint32 &InTrackNum) { m_stopRedbookTemporarily = FALSE; -#if !defined(USE_SDL) - if (!g_theProfileDB->IsUseRedbookAudio() || !c3files_HasCD()) return; -#else if (!g_theProfileDB->IsUseRedbookAudio()) return; - if (!(c3files_HasCD() || m_useOggTracks)) return; +#if defined(USE_SDL) + if (!m_useOggTracks) return; +#else + if (!c3files_HasCD()) return; #endif if (m_noSound) return; @@ -943,19 +867,7 @@ void SoundManager::StartMusic(const sint32 &InTrackNum) else printf("Error, music track %s not found\n", buf); - return; } - if (!m_cdrom) { - return; - } - - CDstatus status = SDL_CDStatus(m_cdrom); - - if ((CD_ERROR == status) || (!CD_INDRIVE(status))) { - return; - } - - sint32 const numTracks = m_cdrom->numtracks; #else if (!m_redbook) { return; @@ -972,8 +884,6 @@ void SoundManager::StartMusic(const sint32 &InTrackNum) } sint32 const numTracks = AIL_redbook_tracks(m_redbook); -#endif - if (numTracks <= s_startTrack) return; m_numTracks = numTracks; @@ -984,9 +894,6 @@ void SoundManager::StartMusic(const sint32 &InTrackNum) m_curTrack = trackNum; -#if defined(USE_SDL) - SDL_CDPlayTracks(m_cdrom, trackNum, 0, 1, 0); -#else U32 start; U32 end; AIL_redbook_track_info(m_redbook, trackNum, &start, &end); @@ -995,28 +902,29 @@ void SoundManager::StartMusic(const sint32 &InTrackNum) TerminateAllSounds(); AIL_redbook_play(m_redbook, start, end); -#endif +#endif // USE_SDL } void SoundManager::TerminateMusic(void) { - if (!g_theProfileDB->IsUseRedbookAudio() || !c3files_HasCD()) return; + if (!g_theProfileDB->IsUseRedbookAudio()) return; +#if !defined(USE_SDL) + if (!c3files_HasCD()) return; +#endif if (m_noSound) return; if (m_usePlaySound) return; -#if !defined(USE_SDL) // Does not compile and why the hell is this here? -// if (m_useOggTracks) { -// Mix_StopMUS(); -// if(m_oggTrack) { -// Mix_FreeMusic(m_oggTrack); -// m_oggTrack = NULL; -// } -// } - if (!m_redbook) return; +#if defined(USE_SDL) + if (m_useOggTracks) { + if(m_oggTrack) { + Mix_FreeMusic(m_oggTrack); + m_oggTrack = NULL; + } + } #else - if (!m_cdrom) return; + if (!m_redbook) return; #endif m_stopRedbookTemporarily = TRUE; @@ -1025,12 +933,6 @@ void SoundManager::TerminateMusic(void) if (AIL_redbook_track(m_redbook)) { AIL_redbook_stop(m_redbook); } -#else - CDstatus status = SDL_CDStatus(m_cdrom); - - if (CD_PLAYING == status) { - SDL_CDStop(m_cdrom); - } #endif } @@ -1094,11 +996,11 @@ void SoundManager::PlayManagedSound(const MBCHAR *fullFilename, const bool &bNoW #if !defined(USE_SDL) PlaySound(fullFilename, NULL, (SND_ASYNC | SND_FILENAME | (bNoWait ? SND_NOWAIT : 0))); -#else - std::cerr << "SoundManager::StupidPlaySound(" +#else // USE_SDL + std::cerr << "SoundManager::PlayManagedSound(" << fullFilename << ") called." << std::endl; -#endif +#endif // USE_SDL } void SoundManager::ReleaseSoundDriver() @@ -1119,7 +1021,7 @@ void SoundManager::ReleaseSoundDriver() S32 err = AIL_digital_handle_release(dig); Assert(err); -#endif +#endif // USE_SDL } void SoundManager::ReacquireSoundDriver() @@ -1137,5 +1039,5 @@ void SoundManager::ReacquireSoundDriver() Assert(err); AIL_set_digital_master_volume(dig, s_masterVolume); -#endif +#endif // USE_SDL } diff --git a/ctp2_code/sound/soundmanager.h b/ctp2_code/sound/soundmanager.h index 4c2462676..9d16705f1 100644 --- a/ctp2_code/sound/soundmanager.h +++ b/ctp2_code/sound/soundmanager.h @@ -44,8 +44,8 @@ #include "gamesounds.h" #if defined(USE_SDL) -#include -#include +#include +#include #endif template class PointerList; @@ -141,10 +141,6 @@ class SoundManager { void ReleaseSoundDriver(); void ReacquireSoundDriver(); -#if defined(USE_SDL) - void SDL_ChannelCompleteCB(int channel); -#endif - private: PointerList *m_sfxSounds; PointerList *m_voiceSounds; @@ -160,15 +156,13 @@ class SoundManager { BOOL m_noSound; BOOL m_usePlaySound; -#if !defined(USE_SDL) - HREDBOOK m_redbook; -#else - SDL_CD *m_cdrom; +#if defined(USE_SDL) BOOL m_useOggTracks; - Uint32 m_SDLInitFlags; Mix_Music *m_oggTrack; -#endif - uint32 m_timeToCheckCD; +#else // USE_SDL + HREDBOOK m_redbook; +#endif // USE_SDL + uint32 m_timeToCheckMusic; sint32 m_numTracks; sint32 m_curTrack; sint32 m_lastTrack; diff --git a/ctp2_code/ui/aui_common/aui_image.cpp b/ctp2_code/ui/aui_common/aui_image.cpp index 9f3e3ed96..98eb255da 100644 --- a/ctp2_code/ui/aui_common/aui_image.cpp +++ b/ctp2_code/ui/aui_common/aui_image.cpp @@ -37,6 +37,10 @@ #include "aui_pixel.h" #include "aui_ui.h" +#if defined(__AUI_USE_SDL__) + #include +#endif + aui_Image::aui_Image( AUI_ERRCODE *retval, const MBCHAR * filename ) @@ -324,8 +328,10 @@ AUI_ERRCODE aui_BmpImageFormat::Load(MBCHAR const * filename, aui_Image *image ) if (bmp->format->Gmask >> bmp->format->Gshift == 0x1F) fprintf(stderr, "%s L%d: 555 image!\n", __FILE__, __LINE__); if (NULL == surf) { - surf = SDL_DisplayFormat(bmp); - } + SDL_PixelFormat *format = SDL_AllocFormat(aui_SDLSurface::TransformSurfacePixelFormatToSDL(g_ui->PixelFormat())); + surf = SDL_ConvertSurface(bmp, format, 0); + SDL_FreeFormat(format); + } SDL_FreeSurface(bmp); if (NULL == surf) return AUI_ERRCODE_LOADFAILED; diff --git a/ctp2_code/ui/aui_common/aui_listbox.cpp b/ctp2_code/ui/aui_common/aui_listbox.cpp index 8ccecd8f5..2c92ec78e 100644 --- a/ctp2_code/ui/aui_common/aui_listbox.cpp +++ b/ctp2_code/ui/aui_common/aui_listbox.cpp @@ -52,7 +52,7 @@ #include "ldl_file.hpp" #ifdef USE_SDL -#include +#include #endif aui_DragDropWindow *aui_ListBox::m_dragDropWindow = NULL; diff --git a/ctp2_code/ui/aui_common/aui_mouse.cpp b/ctp2_code/ui/aui_common/aui_mouse.cpp index e54403c9a..54784e320 100644 --- a/ctp2_code/ui/aui_common/aui_mouse.cpp +++ b/ctp2_code/ui/aui_common/aui_mouse.cpp @@ -55,34 +55,15 @@ #include "ldl_data.hpp" #include "ldl_file.hpp" -sint32 aui_Mouse::m_mouseRefCount = 0; #ifdef __AUI_USE_DIRECTX__ +sint32 aui_Mouse::m_mouseRefCount = 0; LPCRITICAL_SECTION aui_Mouse::m_lpcs = NULL; -#elif defined(__AUI_USE_SDL__) -SDL_mutex *aui_Mouse::m_lpcs = NULL; -#endif - -#ifdef __AUI_USE_SDL__ -#define k_AUI_MOUSE_THREAD_SLEEP_TIME 10000 -#else #define k_AUI_MOUSE_THREAD_SLEEP_TIME 10 -#endif +#endif // __AUI_USE_DIRECTX__ #include "civapp.h" extern CivApp *g_civApp; -#ifdef LINUX -#include // usleep -#endif - -#ifdef __AUI_USE_SDL__ -BOOL g_mouseShouldTerminateThread = FALSE; -sint32 g_oldX = 0; -sint32 g_oldY = 0; -sint32 g_oldW = 0; -sint32 g_oldH = 0; -#endif - aui_Mouse::aui_Mouse ( AUI_ERRCODE * retval, @@ -110,13 +91,16 @@ AUI_ERRCODE aui_Mouse::InitCommon( void ) } else { m_sensitivity = 1.0; } - m_privateMix = NULL; - m_pickup = NULL; - m_prevPickup = NULL; m_suspendCount = 0; m_showCount = 0; m_reset = TRUE; -#ifndef __AUI_USE_SDL__ + m_flags = 0; + +#ifdef __AUI_USE_DIRECTX__ + m_privateMix = NULL; + m_pickup = NULL; + m_prevPickup = NULL; + m_thread = NULL; m_threadId = 0; m_threadEvent = NULL; @@ -124,41 +108,27 @@ AUI_ERRCODE aui_Mouse::InitCommon( void ) m_suspendEvent = NULL; m_resumeEvent = NULL; m_replyEvent = NULL; -#endif - m_flags = 0; +#endif // __AUI_USE_DIRECTX__ memset( m_cursors, 0, sizeof( m_cursors ) ); memset( &m_data, 0, sizeof( m_data ) ); memset( m_inputs, 0, sizeof( m_inputs ) ); SetClip( NULL ); + #ifdef __AUI_USE_DIRECTX__ GetCursorPos( &m_data.position ); -#elif defined(__AUI_USE_SDL__) - int x = 0, y = 0; - Uint8 state = SDL_GetMouseState(&x, &y); - m_data.position.x = x; - m_data.position.y = y; - g_oldX = g_oldY = g_oldW = g_oldH = 0; -#endif if ( !m_mouseRefCount++ ) { -#ifdef __AUI_USE_DIRECTX__ m_lpcs = new CRITICAL_SECTION; -#elif defined(__AUI_USE_SDL__) - m_lpcs = SDL_CreateMutex(); -#endif Assert( m_lpcs != NULL ); -#ifdef __AUI_USE_DIRECTX__ if ( m_lpcs ) InitializeCriticalSection( m_lpcs ); else -#elif defined(__AUI_USE_SDL__) - if (!m_lpcs) -#endif return AUI_ERRCODE_MEMALLOCFAILED; } +#endif // __AUI_USE_DIRECTX__ return AUI_ERRCODE_OK; } @@ -243,6 +213,7 @@ AUI_ERRCODE aui_Mouse::InitCommonLdl( const MBCHAR *ldlBlock ) m_animDelayList.AddTail( blk->GetInt( k_MOUSE_LDL_ANIMDELAY ) ); } } + ActivateCursor(*m_curCursor); return AUI_ERRCODE_OK; } @@ -278,25 +249,22 @@ aui_Mouse::~aui_Mouse() memset( m_cursors, 0, sizeof( m_cursors ) ); } - DestroyPrivateBuffers(); - m_animIndexList.DeleteAll(); m_animDelayList.DeleteAll(); +#ifdef __AUI_USE_DIRECTX__ + DestroyPrivateBuffers(); + if ( !--m_mouseRefCount ) { if ( m_lpcs ) { -#ifdef __AUI_USE_SDL__ - SDL_DestroyMutex(m_lpcs); -#elif defined(__AUI_USE_DIRECTX__) - DeleteCriticalSection( m_lpcs ); delete m_lpcs; -#endif m_lpcs = NULL; } } +#endif // __AUI_USE_DIRECTX__ } void aui_Mouse::SetClip( sint32 left, sint32 top, sint32 right, sint32 bottom ) @@ -357,6 +325,7 @@ void aui_Mouse::SetCurrentCursor( sint32 index ) if ( index < m_firstIndex || index > m_lastIndex ) return; m_curCursor = m_cursors + index; + ActivateCursor(*m_curCursor); } sint32 aui_Mouse::GetCurrentCursorIndex(void) @@ -377,6 +346,9 @@ void aui_Mouse::SetAnimDelay( uint32 animDelay ) void aui_Mouse::SetAnimIndexes( sint32 firstIndex, sint32 lastIndex ) { + if (firstIndex == m_firstIndex && lastIndex == m_lastIndex) + return; + Assert( firstIndex >= 0 ); if ( firstIndex < 0 ) return; Assert( lastIndex >= 0 ); @@ -386,6 +358,7 @@ void aui_Mouse::SetAnimIndexes( sint32 firstIndex, sint32 lastIndex ) m_firstIndex = firstIndex; m_lastIndex = lastIndex; + SetCurrentCursor(m_firstIndex); } void aui_Mouse::SetAnim( sint32 anim ) @@ -398,20 +371,15 @@ void aui_Mouse::SetAnim( sint32 anim ) AUI_ERRCODE aui_Mouse::Start( void ) { - CreatePrivateBuffers(); + m_curCursor = m_cursors + m_firstIndex; + ActivateCursor(*m_curCursor); #ifdef __AUI_USE_DIRECTX__ - m_thread = - CreateThread( NULL, 0, MouseThreadProc, (LPVOID)this, 0, &m_threadId ); -#elif defined(__AUI_USE_SDL__) - m_thread = SDL_CreateThread(MouseThreadProc, this); -#endif - - m_curCursor = m_cursors + m_firstIndex; + CreatePrivateBuffers(); + m_thread = CreateThread( NULL, 0, MouseThreadProc, (LPVOID)this, 0, &m_threadId ); if ( m_thread ) { -#ifdef __AUI_USE_DIRECTX__ SetThreadPriority( m_thread, THREAD_PRIORITY_NORMAL ); m_threadEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); @@ -419,14 +387,16 @@ AUI_ERRCODE aui_Mouse::Start( void ) m_suspendEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); m_resumeEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); m_replyEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); -#endif Acquire(); } +#endif // __AUI_USE_DIRECTX__ return AUI_ERRCODE_OK; } +#ifdef __AUI_USE_DIRECTX__ + AUI_ERRCODE aui_Mouse::CreatePrivateBuffers( void ) { AUI_ERRCODE errcode = AUI_ERRCODE_OK; @@ -460,13 +430,15 @@ void aui_Mouse::DestroyPrivateBuffers( void ) m_prevPickup = NULL; } +#endif // __AUI_USE_DIRECTX__ + AUI_ERRCODE aui_Mouse::End( void ) { +#ifdef __AUI_USE_DIRECTX__ Unacquire(); if ( m_thread ) { -#ifdef __AUI_USE_DIRECTX__ if ( m_threadEvent && m_terminateEvent ) { SetEvent( m_terminateEvent ); @@ -483,13 +455,9 @@ AUI_ERRCODE aui_Mouse::End( void ) } else TerminateThread( m_thread, 1 ); -#elif defined(__AUI_USE_SDL__) - SDL_KillThread(m_thread); -#endif Erase(); -#ifdef __AUI_USE_DIRECTX__ if ( m_suspendEvent ) { CloseHandle( m_suspendEvent ); @@ -511,20 +479,19 @@ AUI_ERRCODE aui_Mouse::End( void ) CloseHandle( m_thread ); m_threadId = 0; -#endif - m_thread = NULL; } -#ifdef __AUI_USE_DIRECTX__ SetCursorPos( m_data.position.x, m_data.position.y ); -#endif +#endif // __AUI_USE_DIRECTX__ return AUI_ERRCODE_OK; } AUI_ERRCODE aui_Mouse::Suspend( BOOL eraseCursor ) { +#ifdef __AUI_USE_DIRECTX__ if ( !m_thread ) return AUI_ERRCODE_NOTHREAD; +#endif // __AUI_USE_DIRECTX__ if ( m_suspendCount ) { @@ -562,12 +529,12 @@ AUI_ERRCODE aui_Mouse::Suspend( BOOL eraseCursor ) AUI_ERRCODE aui_Mouse::Resume( void ) { - +#ifdef __AUI_USE_DIRECTX__ if ( !m_thread ) return AUI_ERRCODE_NOTHREAD; +#endif // __AUI_USE_DIRECTX__ if ( m_suspendCount == 0 ) return AUI_ERRCODE_OK; - if ( m_suspendCount > 1 ) { m_suspendCount--; @@ -596,9 +563,11 @@ AUI_ERRCODE aui_Mouse::Resume( void ) #endif } +#ifdef __AUI_USE_DIRECTX__ + inline BOOL aui_Mouse::ShouldTerminateThread( void ) { -#ifdef __AUI_USE_DIRECTX__ + if ( WaitForSingleObject( m_threadEvent, 0 ) == WAIT_OBJECT_0 ) { ResetEvent( m_threadEvent ); @@ -620,27 +589,16 @@ inline BOOL aui_Mouse::ShouldTerminateThread( void ) } } return FALSE; - -#elif defined(__AUI_USE_SDL__) - return g_mouseShouldTerminateThread; -#endif } -#ifdef __AUI_USE_SDL__ -int MouseThreadProc(void *param) -#elif defined(__AUI_USE_DIRECTX__) DWORD WINAPI MouseThreadProc( LPVOID param ) -#endif { aui_Mouse *mouse = (aui_Mouse *)param; while ( !mouse->ShouldTerminateThread() ) { -#ifdef WIN32 Sleep(k_AUI_MOUSE_THREAD_SLEEP_TIME); -#elif defined(LINUX) - usleep(k_AUI_MOUSE_THREAD_SLEEP_TIME); -#endif + // For that something is wrong with the mouse delay // std::this_thread::sleep_for(std::chrono::milliseconds(k_AUI_MOUSE_THREAD_SLEEP_TIME)); @@ -653,6 +611,8 @@ DWORD WINAPI MouseThreadProc( LPVOID param ) return 0; } +#endif // __AUI_USE_DIRECTX__ + AUI_ERRCODE aui_Mouse::SetPosition( sint32 x, sint32 y ) { if ( x < m_clip.left ) x = m_clip.left; @@ -705,6 +665,7 @@ AUI_ERRCODE aui_Mouse::SetHotspot( sint32 x, sint32 y, sint32 index ) AUI_ERRCODE aui_Mouse::ReactToInput( void ) { +#ifdef __AUI_USE_DIRECTX__ if ( IsHidden() || ((*m_curCursor) == NULL)) return AUI_ERRCODE_OK; POINT hotspot; @@ -877,6 +838,7 @@ AUI_ERRCODE aui_Mouse::ReactToInput( void ) CopyRect( &prevRect, &rect ); CopyRect( &prevUnclippedMixRect, &unclippedMixRect ); +#endif // __AUI_USE_DIRECTX__ return AUI_ERRCODE_OK; } @@ -886,8 +848,10 @@ AUI_ERRCODE aui_Mouse::HandleAnim( void ) if ( m_lastIndex >= m_firstIndex ) { - if(m_curCursor < m_cursors + m_firstIndex) + if(m_curCursor < m_cursors + m_firstIndex) { m_curCursor = m_cursors + m_firstIndex; + ActivateCursor(*m_curCursor); + } uint32 now = GetTickCount(); if ( now - m_time > m_animDelay ) @@ -895,7 +859,7 @@ AUI_ERRCODE aui_Mouse::HandleAnim( void ) if ( m_curCursor++ >= m_cursors + m_lastIndex ) m_curCursor = m_cursors + m_firstIndex; - + ActivateCursor(*m_curCursor); m_time = now; return AUI_ERRCODE_HANDLED; @@ -908,6 +872,8 @@ AUI_ERRCODE aui_Mouse::HandleAnim( void ) AUI_ERRCODE aui_Mouse::BltWindowToPrimary( aui_Window *window ) { AUI_ERRCODE retcode = AUI_ERRCODE_OK; + +#ifdef __AUI_USE_DIRECTX__ AUI_ERRCODE errcode; sint32 windowX = window->X(); @@ -990,12 +956,7 @@ AUI_ERRCODE aui_Mouse::BltWindowToPrimary( aui_Window *window ) &screenDirtyRect, RGB(255,255,255), 0 ); -#ifdef WIN32 Sleep( 20 ); -#elif defined(LINUX) - struct timespec t = { 0, 20000000L }; - nanosleep(&t, NULL); -#endif fclose(f); } #endif @@ -1027,6 +988,7 @@ AUI_ERRCODE aui_Mouse::BltWindowToPrimary( aui_Window *window ) break; } } +#endif // __AUI_USE_DIRECTX__ return retcode; } @@ -1034,6 +996,8 @@ AUI_ERRCODE aui_Mouse::BltWindowToPrimary( aui_Window *window ) AUI_ERRCODE aui_Mouse::BltDirtyRectInfoToPrimary( void ) { AUI_ERRCODE retcode = AUI_ERRCODE_OK; + +#ifdef __AUI_USE_DIRECTX__ AUI_ERRCODE errcode; if (g_civApp->IsInBackground()) return retcode; @@ -1139,12 +1103,7 @@ AUI_ERRCODE aui_Mouse::BltDirtyRectInfoToPrimary( void ) &screenDirtyRect, RGB(255,255,255), 0 ); -#ifdef WIN32 Sleep( 20 ); -#elif defined(LINUX) - struct timespec t = { 0, 20000000L }; - nanosleep(&t, NULL); -#endif } #endif @@ -1192,6 +1151,7 @@ AUI_ERRCODE aui_Mouse::BltDirtyRectInfoToPrimary( void ) errcode = g_ui->Secondary()->Unlock( primaryBuf ); Assert( errcode == AUI_ERRCODE_OK ); } +#endif // __AUI_USE_DIRECTX__ return retcode; } @@ -1201,6 +1161,8 @@ AUI_ERRCODE aui_Mouse::BltBackgroundColorToPrimary( aui_DirtyList *colorAreas ) { AUI_ERRCODE retcode = AUI_ERRCODE_OK; + +#ifdef __AUI_USE_DIRECTX__ AUI_ERRCODE errcode; if (g_civApp->IsInBackground()) return retcode; @@ -1311,6 +1273,7 @@ AUI_ERRCODE aui_Mouse::BltBackgroundColorToPrimary( } } } +#endif // __AUI_USE_DIRECTX__ return retcode; } @@ -1321,6 +1284,8 @@ AUI_ERRCODE aui_Mouse::BltBackgroundImageToPrimary( aui_DirtyList *imageAreas ) { AUI_ERRCODE retcode = AUI_ERRCODE_OK; + +#ifdef __AUI_USE_DIRECTX__ AUI_ERRCODE errcode; if (g_civApp->IsInBackground()) return retcode; @@ -1445,10 +1410,13 @@ AUI_ERRCODE aui_Mouse::BltBackgroundImageToPrimary( } } } +#endif // __AUI_USE_DIRECTX__ return retcode; } +#ifdef __AUI_USE_DIRECTX__ + AUI_ERRCODE aui_Mouse::Erase( void ) { AUI_ERRCODE errcode; @@ -1485,16 +1453,18 @@ AUI_ERRCODE aui_Mouse::Erase( void ) return AUI_ERRCODE_OK; } + +#endif // __AUI_USE_DIRECTX__ + sint32 aui_Mouse::ManipulateInputs( aui_MouseEvent *data, BOOL add ) { sint32 numManipulated = 0; - static sint32 index = 0; #ifdef __AUI_USE_DIRECTX__ + + static sint32 index = 0; + EnterCriticalSection( m_lpcs ); -#elif defined(__AUI_USE_SDL__) - SDL_mutexP(m_lpcs); -#endif if ( add ) { @@ -1534,11 +1504,8 @@ sint32 aui_Mouse::ManipulateInputs( aui_MouseEvent *data, BOOL add ) index = 0; } -#ifdef __AUI_USE_DIRECTX__ LeaveCriticalSection( m_lpcs ); -#elif defined(__AUI_USE_SDL__) - SDL_mutexV(m_lpcs); -#endif +#endif // __AUI_USE_DIRECTX__ return numManipulated; } diff --git a/ctp2_code/ui/aui_common/aui_mouse.h b/ctp2_code/ui/aui_common/aui_mouse.h index 4b82d5cc2..1921a4870 100644 --- a/ctp2_code/ui/aui_common/aui_mouse.h +++ b/ctp2_code/ui/aui_common/aui_mouse.h @@ -24,7 +24,7 @@ // Modifications from the original Activision code: // // - Increased k_MOUSE_MAXNUMCURSORS to allow some additional cursors. -// - April 30th 2005 Martin Gühmann +// - April 30th 2005 Martin Gühmann // //---------------------------------------------------------------------------- @@ -35,11 +35,6 @@ #include "aui_input.h" #include "tech_wllist.h" -#ifdef USE_SDL -#include -#include -#endif - class aui_Cursor; class aui_Surface; class aui_Window; @@ -47,12 +42,6 @@ class aui_Image; class aui_DirtyList; class ldl_datablock; -#ifdef USE_SDL -// HACK: Use this global variable to halt mouse event handling -// thread on game exit -extern BOOL g_mouseShouldTerminateThread; -#endif - #define k_MOUSE_LDL_NUMCURSORS "numcursors" #define k_MOUSE_LDL_ANIM "anim" #define k_MOUSE_LDL_CURSOR "cursor" @@ -166,57 +155,43 @@ class aui_Mouse : public aui_Base, public virtual aui_Input if ( firstIndex ) *firstIndex = m_firstIndex; if ( lastIndex ) * lastIndex = m_lastIndex; } - void SetAnimIndexes( sint32 firstIndex, sint32 lastIndex ); + virtual void SetAnimIndexes( sint32 firstIndex, sint32 lastIndex ); void SetAnim( sint32 anim ); virtual AUI_ERRCODE ReactToInput( void ); - BOOL ShouldTerminateThread( void ); + virtual sint32 ManipulateInputs( aui_MouseEvent *data, BOOL add ); - sint32 ManipulateInputs( aui_MouseEvent *data, BOOL add ); + virtual AUI_ERRCODE HandleAnim( void ); - AUI_ERRCODE HandleAnim( void ); - - AUI_ERRCODE BltWindowToPrimary( aui_Window *window ); - AUI_ERRCODE BltDirtyRectInfoToPrimary( void ); - AUI_ERRCODE BltBackgroundColorToPrimary( + virtual AUI_ERRCODE BltWindowToPrimary( aui_Window *window ); + virtual AUI_ERRCODE BltDirtyRectInfoToPrimary( void ); + virtual AUI_ERRCODE BltBackgroundColorToPrimary( COLORREF color, aui_DirtyList *colorAreas ); - AUI_ERRCODE BltBackgroundImageToPrimary( + virtual AUI_ERRCODE BltBackgroundImageToPrimary( aui_Image *image, RECT *imageRect, aui_DirtyList *imageAreas ); -#ifdef __AUI_USE_SDL__ - SDL_mutex *LPCS(void) const { return m_lpcs; } -#else +#if defined(__AUI_USE_DIRECTX__) LPCRITICAL_SECTION LPCS( void ) const { return m_lpcs; } -#endif - AUI_ERRCODE CreatePrivateBuffers( void ); - void DestroyPrivateBuffers( void ); + BOOL ShouldTerminateThread( void ); +#endif // __AUI_USE_DIRECTX__ uint32 GetFlags(void) { return m_flags;} void SetFlags(uint32 flags) { m_flags = flags; } protected: static sint32 m_mouseRefCount; -#ifdef __AUI_USE_SDL__ - static SDL_mutex* m_lpcs; -#else - static LPCRITICAL_SECTION m_lpcs; -#endif - - virtual AUI_ERRCODE Erase( void ); + virtual void ActivateCursor(aui_Cursor *cursor) {} aui_MouseEvent m_data; double m_sensitivity; aui_MouseEvent m_inputs[ k_MOUSE_MAXINPUT ]; - aui_Surface *m_privateMix; - aui_Surface *m_pickup; - aui_Surface *m_prevPickup; RECT m_clip; aui_Cursor *m_cursors[ k_MOUSE_MAXNUMCURSORS ]; @@ -232,10 +207,18 @@ class aui_Mouse : public aui_Base, public virtual aui_Input sint32 m_suspendCount; sint32 m_showCount; BOOL m_reset; + uint32 m_flags; + +#if defined(__AUI_USE_DIRECTX__) + AUI_ERRCODE CreatePrivateBuffers( void ); + void DestroyPrivateBuffers( void ); + AUI_ERRCODE Erase( void ); + + aui_Surface *m_privateMix; + aui_Surface *m_pickup; + aui_Surface *m_prevPickup; -#ifdef __AUI_USE_SDL__ - SDL_Thread *m_thread; -#elif defined(__AUI_USE_DIRECTX__) + static LPCRITICAL_SECTION m_lpcs; HANDLE m_thread; DWORD m_threadId; HANDLE m_threadEvent; @@ -243,16 +226,11 @@ class aui_Mouse : public aui_Base, public virtual aui_Input HANDLE m_suspendEvent; HANDLE m_resumeEvent; HANDLE m_replyEvent; -#endif - - uint32 m_flags; +#endif // __AUI_USE_DIRECTX__ }; - -#ifdef __AUI_USE_SDL__ -int MouseThreadProc(void *param); -#else +#if defined(__AUI_USE_DIRECTX__) DWORD WINAPI MouseThreadProc( LPVOID lpVoid ); -#endif +#endif // __AUI_USE_DIRECTX__ #endif diff --git a/ctp2_code/ui/aui_common/aui_movie.cpp b/ctp2_code/ui/aui_common/aui_movie.cpp index e5889169d..95a9e94da 100644 --- a/ctp2_code/ui/aui_common/aui_movie.cpp +++ b/ctp2_code/ui/aui_common/aui_movie.cpp @@ -24,7 +24,7 @@ // // Modifications from the original Activision code: // -// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) +// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -36,25 +36,13 @@ #include "aui_movie.h" -#ifdef __AUI_USE_SDL__ -#include -#ifdef USE_SDL_FFMPEG -#include -SDL_ffmpegFile* film; -#endif -#include -#include -#include "soundmanager.h" // g_soundManager -#include "aui_sdlsurface.h" - -Mix_Chunk achunk; - -int m_moviechannel; -#endif - WNDPROC aui_Movie::m_windowProc = NULL; aui_Movie *aui_Movie::m_onScreenMovie = NULL; +aui_Movie::aui_Movie() : aui_Base() { + InitCommon(); +} + aui_Movie::aui_Movie( AUI_ERRCODE *retval, const MBCHAR * filename ) @@ -65,8 +53,7 @@ aui_Movie::aui_Movie( Assert( AUI_SUCCESS(*retval) ); } -AUI_ERRCODE aui_Movie::InitCommon( const MBCHAR * filename ) -{ +void aui_Movie::InitCommon() { m_format = NULL; m_surface = NULL; m_isOpen = FALSE; @@ -89,6 +76,11 @@ AUI_ERRCODE aui_Movie::InitCommon( const MBCHAR * filename ) m_getFrame = NULL; #endif m_curFrame = 0; +} + +AUI_ERRCODE aui_Movie::InitCommon( const MBCHAR * filename ) +{ + InitCommon(); AUI_ERRCODE errcode = SetFilename( filename ); Assert( AUI_SUCCESS(errcode) ); @@ -219,139 +211,6 @@ uint32 aui_Movie::SetTimePerFrame( uint32 timePerFrame ) return prevTimePerFrame; } -#ifdef USE_SDL_FFMPEG -/* -void reload_audio(int channel) -{ - SDL_ffmpegAudioFrame *aframe; - - if(channel == m_moviechannel) - { - if(film) - { - while(!aframe) - aframe= SDL_ffmpegGetAudioFrame(film); - //if(aframe){ - - //while(!aframe->size) - // aframe= SDL_ffmpegGetAudioFrame(file); - achunk.alen= aframe->size; - //achunk.abuf= aframe->buffer; //should we copy the data here??? - if(achunk.abuf) //or use realloc??? - free(achunk.abuf); - achunk.abuf= new uint8_t[achunk.alen]; - memcpy(achunk.abuf, aframe->buffer, achunk.alen); - achunk.allocated= 1; //abuf should not be freed if it belongs to aframe - achunk.volume= MIX_MAX_VOLUME; - - m_moviechannel= Mix_PlayChannel(channel, &achunk , 0); - if(m_moviechannel < 0) - fprintf(stderr, "%s L%d: Error initializing SDL_mixer: %s\n", __FILE__, __LINE__, Mix_GetError()); - //else - // Mix_ChannelFinished(reload_audio); - SDL_ffmpegReleaseAudio(film, aframe, achunk.alen); - } - } - else - fprintf(stderr, "%s L%d: Not a movie audio channel!\n", __FILE__, __LINE__); - - return; -} -*/ - -/* sdl_ffmpeg <= 0.7.1 -void audioCallback(void *udata, Uint8 *stream, int len) -{ - // unpack our void pointer - SDL_ffmpegFile *file = (SDL_ffmpegFile*)udata; - - int bytesUsed; - int offset = 0; - SDL_ffmpegAudioFrame *frame = SDL_ffmpegGetAudioFrame(file); - if(!frame) return; - - while(len > 0) - { - // check if we need a new frame - if(!frame->size) - { - frame = SDL_ffmpegGetAudioFrame(file); - if(!frame) return; - } - - if(frame->size <= len) - { - // this frame is smaller or equal to the amount of data needed. - bytesUsed = frame->size; - } - else - { - // this frame has more data than needed - bytesUsed = len; - } - - // copy the correct amount of data - memcpy(stream+offset, frame->buffer, bytesUsed); - // adjust the needed length accordingly - len -= bytesUsed; - offset += bytesUsed; - - SDL_ffmpegReleaseAudio(file, frame, bytesUsed); - } - - return; -} -*/ -/* sdl_ffmpeg > 0.7.1*/ -void audioCallback(void *udata, Uint8 *stream, int len) -{ - - // unpack our void pointer - SDL_ffmpegFile *file = (SDL_ffmpegFile*)udata; - - int bytesUsed; - - SDL_ffmpegAudioFrame *frame; - - while(len > 0) - { - // try to get a new frame - frame = SDL_ffmpegGetAudioFrame(file); - - // we could not receive a new frame, break from loop - if(!frame) break; - - if(frame->size <= len) - { - // this frame is smaller or equal to the amount of data needed. - bytesUsed = frame->size; - } - else - { - // this frame has more data than needed - bytesUsed = len; - } - - // copy the correct amount of data - memcpy(stream, frame->buffer, bytesUsed); - - // adjust the needed length accordingly - len -= bytesUsed; - - // adjust stream offset - stream += bytesUsed; - - // adjust size of frame to prevent reusing the same data - frame->size -= bytesUsed; - - // adjust buffer of frame for the same reason - frame->buffer += bytesUsed; - } - - return; -} -#endif - AUI_ERRCODE aui_Movie::Open( uint32 flags, aui_Surface *surface, @@ -422,32 +281,6 @@ AUI_ERRCODE aui_Movie::Open( m_rect.right = m_rect.left + m_aviStreamInfo.rcFrame.right; m_rect.bottom = m_rect.top + m_aviStreamInfo.rcFrame.bottom; -#elif defined(USE_SDL_FFMPEG) //replaces a aui_sdlmovie::Open( - - //stop game sound - g_soundManager->ReleaseSoundDriver(); // If the CD is mounted, the music keeps playing ... - - //code from SDL_ffmpeg example: - film= SDL_ffmpegOpen(m_filename); - if (film) - { - SDL_ffmpegSelectVideoStream(film, 0); - SDL_ffmpegSelectAudioStream(film, 0); - - int w, h; - // we get the size from our active video stream - if(SDL_ffmpegGetVideoSize(film, &w, &h)) - fprintf(stderr, "%s L%d: Could not determin movie size!\n", __FILE__, __LINE__); - else - { - m_rect.right = m_rect.left + w; - m_rect.bottom = m_rect.top + h; - } - } - else - { - fprintf(stderr, "%s L%d: Could not open %s!\n", __FILE__, __LINE__, m_filename); - } #endif m_isOpen = TRUE; //even if open failed, loops otherwise m_isPlaying = FALSE; @@ -482,13 +315,6 @@ AUI_ERRCODE aui_Movie::Close( void ) AVIFileRelease( m_aviFile ); m_aviFile = NULL; } -#elif defined(USE_SDL_FFMPEG) - if(film) - { - Mix_HookMusic(NULL,NULL); //switch on the general callback function (sound and music) - SDL_ffmpegStopDecoding(film); - SDL_ffmpegFree(film); - } #endif m_isOpen = FALSE; @@ -511,62 +337,6 @@ AUI_ERRCODE aui_Movie::Play( void ) 1000 ); Assert( err == 0 ); if ( err ) return AUI_ERRCODE_HACK; - -#elif defined(USE_SDL_FFMPEG) - /* - //mplayer "movie manager" - SDL_SysWMinfo info; - char cmd[1024]; - cmd[0]=0; - - SDL_VERSION(&info.version); // this is important! - if (SDL_GetWMInfo(&info)) - snprintf(cmd, sizeof(cmd), "mplayer -vo xv -wid 0x%lx /media/cdrom/Setup/data/Max/ctp2_data/default/videos/%s", info.info.x11.window, m_filename); - else - snprintf(cmd, sizeof(cmd), "mplayer -vo sdl /media/cdrom/Setup/data/Max/ctp2_data/default/videos/%s", m_filename); - fprintf(stderr, "%s L%d: Trying to execute: %s!\n", __FILE__, __LINE__, cmd); - fprintf(stderr, "%s L%d: The path to the movies is hard coded! Solve it! ;)\n", __FILE__, __LINE__); - g_soundManager->ReleaseSoundDriver(); - system(cmd); - g_soundManager->ReacquireSoundDriver();//no function with SDL, see soundmanager.cpp - */ - - // we start our decode thread, this always tries to buffer in some frames - // so we can enjoy smooth playback - if(film) - { - Mix_HookMusic(audioCallback, film); - - // if(Mix_OpenAudio(48000, AUDIO_S16SYS, 2, 512)==-1) - // fprintf(stderr, "%s L%d: Mix_OpenAudio: %s\n", __FILE__, __LINE__, Mix_GetError()); - - SDL_ffmpegStartDecoding(film); //returns always 0! - //SDL_ffmpegPause(film, 0);//unpause film sdl_ffmpeg <= 0.7.1 - SDL_ffmpegPlay(film, 1);//unpause film sdl_ffmpeg > 0.7.1 - //start audio here or in process or open??? -/* - SDL_ffmpegAudioFrame *aframe; - - while(!aframe) - aframe= SDL_ffmpegGetAudioFrame(film); - //if(aframe){ - - //while(!aframe->size) - // aframe= SDL_ffmpegGetAudioFrame(file); - achunk.alen= aframe->size; - //achunk.abuf= aframe->buffer; //should we copy the data here??? - achunk.abuf= new uint8_t[achunk.alen]; - memcpy(achunk.abuf, aframe->buffer, achunk.alen); - achunk.allocated= 1; //abuf should not be freed if it belongs to aframe - Mix_VolumeChunk(&achunk, MIX_MAX_VOLUME); - m_moviechannel= Mix_PlayChannel(-1, &achunk , 0); - if(m_moviechannel < 0) - fprintf(stderr, "%s L%d: Error initializing SDL_mixer: %s\n", __FILE__, __LINE__, Mix_GetError()); - else - Mix_ChannelFinished(reload_audio); - SDL_ffmpegReleaseAudio(film, aframe, achunk.alen); -*/ - } #endif if ( m_flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN ) @@ -581,6 +351,7 @@ AUI_ERRCODE aui_Movie::Play( void ) AUI_ERRCODE aui_Movie::PlayOnScreenMovie( void ) { +#ifdef __AUI_USE_DIRECTX__ aui_Mouse *mouse = g_ui->TheMouse(); sint32 numEvents; static aui_MouseEvent mouseEvents[ k_MOUSE_MAXINPUT ]; @@ -597,7 +368,6 @@ AUI_ERRCODE aui_Movie::PlayOnScreenMovie( void ) mouse->Hide(); } -#ifdef __AUI_USE_DIRECTX__ MSG msg; m_windowProc = (WNDPROC)GetWindowLong( g_ui->TheHWND(), GWL_WNDPROC ); SetWindowLong( g_ui->TheHWND(), GWL_WNDPROC, (LONG)OnScreenMovieWindowProc ); @@ -636,21 +406,12 @@ AUI_ERRCODE aui_Movie::PlayOnScreenMovie( void ) SetWindowLong( g_ui->TheHWND(), GWL_WNDPROC, (LONG)m_windowProc ); m_windowProc = NULL; -#else - fprintf(stderr, "%s L%d: SDL mouse code is missing here!\n", __FILE__, __LINE__); - //m_onScreenMovie = this; - - while(!m_isFinished && m_isPlaying) - { - Process(); - } - //m_onScreenMovie = NULL; -#endif if (mouse) mouse->Show(); g_ui->AddDirtyRect( &m_rect ); // Does this set the rect that needs to be repainted later on? +#endif return Stop(); } @@ -663,16 +424,6 @@ AUI_ERRCODE aui_Movie::Stop( void ) uint32 err = AVIStreamEndStreaming(m_aviStream); Assert(err == 0); if(err) return AUI_ERRCODE_HACK; -#elif defined(USE_SDL_FFMPEG) - fprintf(stderr, "%s L%d: Stopping movie!\n", __FILE__, __LINE__); - if(film) - { - //SDL_ffmpegPause(film, 1);//pause film film sdl_ffmpeg <= 0.7.1 - SDL_ffmpegPlay(film, 0);//pause film sdl_ffmpeg > 0.7.1 - //SDL_ffmpegStopDecoding(film); - } - - g_soundManager->ReacquireSoundDriver(); //no function with SDL, see soundmanager.cpp #endif } @@ -686,11 +437,6 @@ AUI_ERRCODE aui_Movie::Pause(void) { if (m_isPlaying && !m_isPaused) { -#ifdef USE_SDL_FFMPEG - if(film) - //SDL_ffmpegPause(film, 1);//pause film sdl_ffmpeg <= 0.7.1 - SDL_ffmpegPlay(film, 0);//pause film sdl_ffmpeg > 0.7.1 -#endif m_isPaused = TRUE; } @@ -701,11 +447,6 @@ AUI_ERRCODE aui_Movie::Resume(void) { if (m_isPlaying && m_isPaused) { -#ifdef USE_SDL_FFMPEG - if(film) - //SDL_ffmpegPause(film, 0);//unpause film sdl_ffmpeg <= 0.7.1 - SDL_ffmpegPlay(film, 1);//unpause film sdl_ffmpeg > 0.7.1 -#endif m_isPaused = FALSE; } @@ -785,86 +526,6 @@ AUI_ERRCODE aui_Movie::Process( void ) retval = AUI_ERRCODE_HANDLED; } } -#elif defined(USE_SDL_FFMPEG) - - //from SDL_ffmpeg example: - if(m_isPlaying && !m_isPaused) - { - if(film) - { - aui_Surface *surface = (m_flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN) ? - g_ui->Secondary() : - m_surface; - - int s; - SDL_ffmpegStream *str; - -/* - // print some info on detected stream to output - for(s = 0; sAStreams; s++) - { - str = SDL_ffmpegGetAudioStream(film, s); - - printf("Info on audiostream #%i:\n", s); - printf("\tChannels: %i\n", str->channels); - if(strlen(str->language)) printf("\tLanguage: %s\n", str->language); - printf("\tSampleRate: %i\n", str->sampleRate); - } - - - for(s = 0; sVStreams; s++) - { - str = SDL_ffmpegGetVideoStream(film, s); - - printf("Info on videostream #%i:\n", s); - if(strlen(str->language)) printf("\tLanguage: %s\n", str->language); - printf("\tFrame: %ix%i\n", str->width, str->height); - printf("\tFrameRate: %.2ffps\n", 1.0 / (str->frameRate[0] / str->frameRate[1])); - } -*/ - - SDL_ffmpegVideoFrame* frame = 0; - - SDL_Rect sdl_rect = {m_rect.left, m_rect.top, m_rect.right - m_rect.left, m_rect.bottom - m_rect.top}; - aui_SDLSurface* sdl_surf = static_cast(surface); - - int64_t duration = SDL_ffmpegGetDuration(film); - - //if(!m_isFinished) {//don't wait until frame is ready to be shown - while(!frame && !m_isFinished) - { //wait until there is a frame to be shown - frame = SDL_ffmpegGetVideoFrame(film); - SDL_Delay(5); //too much for 25 fps but here we have only 15 fps - - if(frame) - { - //fprintf(stderr, "%s L%d: Got frame!\n", __FILE__, __LINE__); - - // we got a frame, so we better show this one - SDL_BlitSurface(frame->buffer, 0, sdl_surf->DDS(), &sdl_rect); - - // After releasing this frame, you can no longer use it. - // you should call this function every time you get a frame! - //not in sdl_ffmpeg > 0.7.1!!! - //SDL_ffmpegReleaseVideo(film, frame); - - // we flip the double buffered screen so we might actually see something - SDL_Flip(sdl_surf->DDS()); - } - m_isFinished = SDL_ffmpegGetPosition(film) >= duration; - //m_isFinished= film->playing; - } - - if(m_isFinished) - { - //fprintf(stderr, "%s L%d: Done displaying movie!\n", __FILE__, __LINE__); - m_isPlaying = FALSE; - } - } - else - m_isFinished = TRUE; -} - retval = AUI_ERRCODE_HANDLED; #endif return retval; diff --git a/ctp2_code/ui/aui_common/aui_movie.h b/ctp2_code/ui/aui_common/aui_movie.h index 409ca586a..e5ccea91d 100644 --- a/ctp2_code/ui/aui_common/aui_movie.h +++ b/ctp2_code/ui/aui_common/aui_movie.h @@ -56,19 +56,20 @@ class aui_MovieFormat : public aui_FileFormat class aui_Movie : public aui_Base { public: - + aui_Movie( void ); aui_Movie( AUI_ERRCODE *retval, const MBCHAR * filename = NULL ); virtual ~aui_Movie(); protected: + void InitCommon( void ); AUI_ERRCODE InitCommon( const MBCHAR * filename ); public: - AUI_ERRCODE Load( void ); - AUI_ERRCODE Unload( void ); + virtual AUI_ERRCODE Load( void ); + virtual AUI_ERRCODE Unload( void ); AUI_ERRCODE SetFilename( const MBCHAR * filename ); const MBCHAR *GetFilename( void ) const { return m_filename; } @@ -106,10 +107,10 @@ class aui_Movie : public aui_Base virtual AUI_ERRCODE Process( void ); - BOOL IsOpen( void ) const { return m_isOpen; } - BOOL IsPlaying( void ) const { return m_isPlaying; } - BOOL IsFinished( void ) const { return m_isFinished; } - BOOL IsPaused( void ) const { return m_isPaused; } + virtual BOOL IsOpen( void ) const { return m_isOpen; } + virtual BOOL IsPlaying( void ) const { return m_isPlaying; } + virtual BOOL IsFinished( void ) const { return m_isFinished; } + virtual BOOL IsPaused( void ) const { return m_isPaused; } static WNDPROC m_windowProc; static aui_Movie *m_onScreenMovie; diff --git a/ctp2_code/ui/aui_common/aui_moviebutton.cpp b/ctp2_code/ui/aui_common/aui_moviebutton.cpp index d00e31cea..6cf267244 100644 --- a/ctp2_code/ui/aui_common/aui_moviebutton.cpp +++ b/ctp2_code/ui/aui_common/aui_moviebutton.cpp @@ -172,6 +172,11 @@ AUI_ERRCODE aui_MovieButton::Idle( void ) if (m_ActionFunc) m_ActionFunc((aui_Control *)this, AUI_BUTTON_ACTION_EXECUTE, 0, NULL); } +#if defined(USE_SDL) + else { + m_window->AddDirtyRect( m_x, m_y, m_x + m_width, m_y + m_height ); + } +#endif // USE_SDL } } diff --git a/ctp2_code/ui/aui_common/aui_music.cpp b/ctp2_code/ui/aui_common/aui_music.cpp index c061aea9b..024ab17e0 100644 --- a/ctp2_code/ui/aui_common/aui_music.cpp +++ b/ctp2_code/ui/aui_common/aui_music.cpp @@ -38,7 +38,6 @@ m_ctrack(-1), m_volume(0xff), m_pause(FALSE) { - return; } aui_Music::~aui_Music() @@ -58,12 +57,10 @@ aui_Music::SetVolume( uint8 volume ) return AUI_MUSIC_ERRCODE_OK; } +#if !defined(USE_SDL) + aui_Redbook::aui_Redbook() : -#ifdef __AUI_USE_DIRECTX__ m_cd_device_id(-1), -#elif defined(__AUI_USE_SDL__) -m_cd_device_id(0), -#endif m_cd_drive_num(0), m_cd_drive_index(0), m_cd_ok(FALSE), @@ -74,11 +71,7 @@ m_aux_cdrom_id(-1) aui_Redbook::~aui_Redbook() { -#ifdef __AUI_USE_DIRECTX__ m_cd_device_id = -1; -#elif defined(__AUI_USE_SDL__) - m_cd_device_id = 0; -#endif m_cd_drive_num = 0; m_cd_drive_index = 0; m_aux_cdrom_id = -1; @@ -88,7 +81,6 @@ aui_Redbook::~aui_Redbook() AUI_MUSIC_ERRCODE aui_Redbook::Init() { -#ifdef __AUI_USE_DIRECTX__ MCIERROR returnVal; MCI_OPEN_PARMS mciOpenParms; MCI_SET_PARMS mciSetParms; @@ -146,7 +138,6 @@ aui_Redbook::Init() } m_ntracks = mciStatusParms.dwReturn; -#endif m_first_track = 1; m_last_track = m_ntracks; @@ -159,57 +150,40 @@ aui_Redbook::Init() AUI_MUSIC_ERRCODE aui_Redbook::Close() { -#ifdef __AUI_USE_DIRECTX__ Stop(); return CDDone(); -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } AUI_MUSIC_ERRCODE aui_Redbook::Pause() { -#ifdef __AUI_USE_DIRECTX__ MCI_GENERIC_PARMS mciPauseParms; sint32 mci_retval = mciSendCommand( m_cd_device_id, MCI_PAUSE, 0, (DWORD)&mciPauseParms ); return mci_retval ? AUI_MUSIC_ERRCODE_MCIERR : AUI_MUSIC_ERRCODE_OK; -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } AUI_MUSIC_ERRCODE aui_Redbook::Resume() { -#ifdef __AUI_USE_DIRECTX__ MCI_GENERIC_PARMS mciResumeParms; sint32 mci_retval = mciSendCommand( m_cd_device_id, MCI_RESUME, 0, (DWORD)&mciResumeParms ); return mci_retval ? AUI_MUSIC_ERRCODE_MCIERR : AUI_MUSIC_ERRCODE_OK; -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } AUI_MUSIC_ERRCODE aui_Redbook::Stop() { -#ifdef __AUI_USE_DIRECTX__ MCI_GENERIC_PARMS mciStopParms; sint32 mci_retval = mciSendCommand( m_cd_device_id, MCI_STOP, 0, (DWORD)&mciStopParms ); return mci_retval ? AUI_MUSIC_ERRCODE_MCIERR : AUI_MUSIC_ERRCODE_OK; -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } AUI_MUSIC_ERRCODE aui_Redbook::Play( sint32 itrack ) { -#ifdef __AUI_USE_DIRECTX__ if( (itrack < m_first_track) || (itrack > m_last_track) ) return AUI_MUSIC_ERRCODE_INVALID_TRACKNUMBER; @@ -222,29 +196,21 @@ aui_Redbook::Play( sint32 itrack ) m_ctrack = itrack; return mci_retval ? AUI_MUSIC_ERRCODE_MCIERR : AUI_MUSIC_ERRCODE_OK; -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } AUI_MUSIC_ERRCODE aui_Redbook::Play() { -#ifdef __AUI_USE_DIRECTX__ MCI_PLAY_PARMS mciPlayParms; sint32 mci_retval = mciSendCommand(m_cd_device_id, MCI_PLAY, 0, (DWORD)&mciPlayParms); return mci_retval ? AUI_MUSIC_ERRCODE_MCIERR : AUI_MUSIC_ERRCODE_OK; -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } AUI_MUSIC_ERRCODE aui_Redbook::SetVolume( uint8 volume ) { -#ifdef __AUI_USE_DIRECTX__ m_volume = volume; if (m_aux_cdrom_id == -1) @@ -257,16 +223,12 @@ aui_Redbook::SetVolume( uint8 volume ) sint32 mci_retval = auxSetVolume(m_aux_cdrom_id, CDvolume); return mci_retval ? AUI_MUSIC_ERRCODE_MCIERR : AUI_MUSIC_ERRCODE_OK; -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } sint32 aui_Redbook::CDInitVolume() { int CDRomID = -1; -#ifdef __AUI_USE_DIRECTX__ int HowManyAuxDevices = auxGetNumDevs(); if (HowManyAuxDevices > 0) @@ -311,7 +273,6 @@ aui_Redbook::CDInitVolume() } } } -#endif return( CDRomID ); } @@ -319,7 +280,6 @@ aui_Redbook::CDInitVolume() AUI_MUSIC_ERRCODE aui_Redbook::GetCDIndex() { -#ifdef __AUI_USE_DIRECTX__ LPSTR driveMap = (LPSTR) calloc(105, sizeof(char)); GetLogicalDriveStrings(105, driveMap); @@ -342,7 +302,6 @@ aui_Redbook::GetCDIndex() m_cd_drive_index = 0; free(driveMap); -#endif return AUI_MUSIC_ERRCODE_OK; } @@ -350,23 +309,18 @@ aui_Redbook::GetCDIndex() AUI_MUSIC_ERRCODE aui_Redbook::CDDone() { -#ifdef __AUI_USE_DIRECTX__ MCI_GENERIC_PARMS mciCloseParms; sint32 mci_retval = mciSendCommand( m_cd_device_id, MCI_CLOSE, 0, (DWORD)(&mciCloseParms) ); m_cd_device_id = -1; return mci_retval? AUI_MUSIC_ERRCODE_MCIERR : AUI_MUSIC_ERRCODE_OK; -#else - return AUI_MUSIC_ERRCODE_OK; -#endif } AUI_MUSIC_CODE aui_Redbook::Status() { -#ifdef __AUI_USE_DIRECTX__ if (m_cd_ok) { MCI_STATUS_PARMS mciStatusParms; @@ -402,7 +356,6 @@ aui_Redbook::Status() } return AUI_MUSIC_CODE_UNKNOWN; -#else - return AUI_MUSIC_CODE_EMPTY; -#endif } + +#endif // USE_SDL diff --git a/ctp2_code/ui/aui_common/aui_music.h b/ctp2_code/ui/aui_common/aui_music.h index 96cc128d5..ad35e209c 100644 --- a/ctp2_code/ui/aui_common/aui_music.h +++ b/ctp2_code/ui/aui_common/aui_music.h @@ -2,10 +2,6 @@ #define __AUI_MUSIC_H__ #include "aui_base.h" -#ifdef USE_SDL -#include -#include -#endif enum AUI_MUSIC_CODE { @@ -70,6 +66,8 @@ class aui_Music : public aui_Base }; +#if !defined(USE_SDL) + class aui_Redbook : public aui_Music { public: @@ -95,11 +93,7 @@ class aui_Redbook : public aui_Music protected: -#ifdef __AUI_USE_DIRECTX__ sint32 m_cd_device_id; -#elif defined(__AUI_USE_SDL__) - SDL_CD*m_cd_device_id; -#endif int m_cd_drive_num; sint32 m_cd_drive_index; BOOL m_cd_ok; @@ -107,4 +101,6 @@ class aui_Redbook : public aui_Music }; +#endif // USE_SDL + #endif diff --git a/ctp2_code/ui/aui_common/aui_resource.h b/ctp2_code/ui/aui_common/aui_resource.h index dfea98d85..b4c1067d3 100644 --- a/ctp2_code/ui/aui_common/aui_resource.h +++ b/ctp2_code/ui/aui_common/aui_resource.h @@ -162,8 +162,8 @@ aui_Resource::aui_Resource() template aui_Resource::~aui_Resource() { - Assert(!m_resourceList); -// diabled because SetPointSize needed in linux debug version before m_surfaceList is populated Assert((m_resourceList->L() == 0)); + // disabled because SetPointSize needed in linux debug version before m_surfaceList is populated + // Assert(!m_resourceList || (m_resourceList->L() == 0)); delete m_resourceList; m_resourceList = NULL; diff --git a/ctp2_code/ui/aui_common/aui_surface.cpp b/ctp2_code/ui/aui_common/aui_surface.cpp index 1c00b5b69..b3d4bd836 100644 --- a/ctp2_code/ui/aui_common/aui_surface.cpp +++ b/ctp2_code/ui/aui_common/aui_surface.cpp @@ -25,7 +25,7 @@ // Modifications from the original Activision code: // // - Corrected a reported memory leak. -// - Added back buffering capability. (1-Jan-2010 Martin G�hmann) +// - Added back buffering capability. (1-Jan-2010 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -109,6 +109,21 @@ aui_Surface::aui_Surface( } } +AUI_SURFACE_PIXELFORMAT aui_Surface::TransformBppToSurfacePixelFormat(int bpp) +{ + switch (bpp) { + case 8: + return AUI_SURFACE_PIXELFORMAT_332; + case 16: + return g_is565Format ? AUI_SURFACE_PIXELFORMAT_565 : AUI_SURFACE_PIXELFORMAT_555; + case 24: + case 32: + return AUI_SURFACE_PIXELFORMAT_888; + default: + return AUI_SURFACE_PIXELFORMAT_UNKNOWN; + } +} + AUI_ERRCODE aui_Surface::InitCommon( sint32 width, sint32 height, sint32 bpp, BOOL isPrimary ) { m_pixelFormat = AUI_SURFACE_PIXELFORMAT_UNKNOWN, @@ -145,9 +160,6 @@ AUI_ERRCODE aui_Surface::InitCommon( sint32 width, sint32 height, sint32 bpp, BO #endif } - - - if ( bpp == 16 ) if (g_is565Format) { m_pixelFormat = AUI_SURFACE_PIXELFORMAT_565; diff --git a/ctp2_code/ui/aui_common/aui_surface.h b/ctp2_code/ui/aui_common/aui_surface.h index 6d7ce9f27..04c352a82 100644 --- a/ctp2_code/ui/aui_common/aui_surface.h +++ b/ctp2_code/ui/aui_common/aui_surface.h @@ -24,7 +24,7 @@ // Modifications from the original Activision code: // // - Corrected a reported memory leak. -// - Added back buffering capability. (1-Jan-2010 Martin Gühmann) +// - Added back buffering capability. (1-Jan-2010 Martin Gühmann) // //---------------------------------------------------------------------------- #if defined(HAVE_PRAGMA_ONCE) @@ -36,8 +36,8 @@ #include "aui_base.h" #ifdef USE_SDL -#include -#include +#include +#include #endif enum AUI_SURFACE_PIXELFORMAT @@ -88,6 +88,8 @@ class aui_Surface : public aui_Base AUI_ERRCODE InitCommon( sint32 width, sint32 height, sint32 bpp, BOOL isPrimary ); public: + static AUI_SURFACE_PIXELFORMAT TransformBppToSurfacePixelFormat(int bpp); + virtual BOOL IsThisA( uint32 classId ) { return classId == m_surfaceClassId; diff --git a/ctp2_code/ui/aui_common/aui_ui.cpp b/ctp2_code/ui/aui_common/aui_ui.cpp index 46823048b..d539ea7a8 100644 --- a/ctp2_code/ui/aui_common/aui_ui.cpp +++ b/ctp2_code/ui/aui_common/aui_ui.cpp @@ -1104,26 +1104,7 @@ AUI_ERRCODE aui_UI::Draw( void ) ShowSelectedRegion( m_editRegion ); } #ifdef __AUI_USE_SDL__ - // refresh screen - SDL_Surface * screen = SDL_GetVideoSurface(); - /*if(m_dirtyRectInfoList->L()) { - ListPos position = m_dirtyRectInfoList->GetHeadPosition(); - for ( sint32 i = m_dirtyRectInfoList->L(); i; i-- ) { - DirtyRectInfo *dri = m_dirtyRectInfoList->GetNext( position ); - sint32 dX = dri->rect.left + dri->window->X(); - sint32 dY = dri->rect.top + dri->window->Y(); - sint32 dW = dri->rect.right - dri->rect.left; - sint32 dH = dri->rect.bottom - dri->rect.top; - if(dX<0) dX = 0; if(dX>=screen->w) dX = screen->w-1; - if(dY<0) dY = 0; if(dY>=screen->h) dY = screen->h-1; - if(dX+dW>screen->w) dW = screen->w-dX; - if(dY+dH>screen->h) dH = screen->h-dY; - if(dW>0 && dH>0) { - SDL_UpdateRect(screen, dX, dY, dW, dH); - } - } - }*/ - SDL_Flip(screen); + SDLDrawScreen(); #endif errcode = m_mouse->Resume(); Assert( errcode == AUI_ERRCODE_OK ); diff --git a/ctp2_code/ui/aui_common/aui_ui.h b/ctp2_code/ui/aui_common/aui_ui.h index e2bfbd9e5..44b31e10c 100644 --- a/ctp2_code/ui/aui_common/aui_ui.h +++ b/ctp2_code/ui/aui_common/aui_ui.h @@ -410,6 +410,10 @@ class aui_UI : public aui_Region virtual AUI_ERRCODE ClipAndConsolidate( void ); +#ifdef __AUI_USE_SDL__ + virtual AUI_ERRCODE SDLDrawScreen( void ) {} +#endif + AUI_ERRCODE InsertDirtyRectInfo( RECT *rect, aui_Window *window ); void FlushDirtyRectInfoList( void ); diff --git a/ctp2_code/ui/aui_common/auitypes.h b/ctp2_code/ui/aui_common/auitypes.h index 7d909e7ce..d40317bb1 100644 --- a/ctp2_code/ui/aui_common/auitypes.h +++ b/ctp2_code/ui/aui_common/auitypes.h @@ -80,6 +80,7 @@ enum AUI_ERRCODE AUI_ERRCODE_SETPROPERTYFAILED, AUI_ERRCODE_SETFORMATFAILED, //#endif + AUI_ERRCODE_MOVIEFAILED, AUI_ERRCODE_MAX }; diff --git a/ctp2_code/ui/aui_ctp2/SelItem.cpp b/ctp2_code/ui/aui_ctp2/SelItem.cpp index 847efea7f..32553120a 100644 --- a/ctp2_code/ui/aui_ctp2/SelItem.cpp +++ b/ctp2_code/ui/aui_ctp2/SelItem.cpp @@ -29,15 +29,15 @@ // correct stop player is set. // - #01 Standardization of city selection and focus handling // (L. Hirth 6/2004) -// - Entrenching units are treated like Entrenched units. (Oct 16th 2005 Martin Gühmann) -// - Added select city instead of army option. (Oct 16th 2005 Martin Gühmann) +// - Entrenching units are treated like Entrenched units. (Oct 16th 2005 Martin Gühmann) +// - Added select city instead of army option. (Oct 16th 2005 Martin Gühmann) // - Added option to avoid an end turn if there are cities with empty build -// queues. (Oct. 22nd 2005 Martin Gühmann) Doesn't really work. +// queues. (Oct. 22nd 2005 Martin Gühmann) Doesn't really work. // - Added option to allow end turn if the game runs in the background, -// useful for automatic AI testing. (Oct. 22nd 2005 Martin Gühmann) -// - Added debug pathing for the city astar. (17-Jan-2008 Martin Gühmann) +// useful for automatic AI testing. (Oct. 22nd 2005 Martin Gühmann) +// - Added debug pathing for the city astar. (17-Jan-2008 Martin Gühmann) // - If the keyboard is used for moving the map is only centered if the auto -// center option is active. (23-Feb-2008 Martin Gühmann) +// center option is active. (23-Feb-2008 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -255,7 +255,7 @@ SelectedItem::SelectedItem(CivArchive &archive) SetPlayerOnScreen(m_current_player); - //Added by Martin Gühmann + //Added by Martin Gühmann //To make sure that save games saved with other players than //player one can be continued without using the cheat editor. NewTurnCount::SetStopPlayer(m_current_player); @@ -662,6 +662,9 @@ void SelectedItem::NextUnmovedUnit(bool isFirst, bool manualNextUnit) double SelectedItem::UnitsDoneRatio(){ Player *p = g_player[GetVisiblePlayer()]; sint32 numUnits= p->m_all_armies->Num(); + if (numUnits == 0) { + return 1.0; + } sint32 unitsDone= numUnits; for(sint32 u = numUnits - 1; u >= 0; u--){ @@ -676,6 +679,9 @@ double SelectedItem::UnitsDoneRatio(){ double SelectedItem::UnitsBusyRatio(){ Player *p = g_player[GetVisiblePlayer()]; sint32 numUnits= p->m_all_armies->Num(); + if (numUnits == 0) { + return 0.0; + } sint32 unitsDone= numUnits; for(sint32 u = numUnits - 1; u >= 0; u--){ diff --git a/ctp2_code/ui/aui_ctp2/c3imageformats.cpp b/ctp2_code/ui/aui_ctp2/c3imageformats.cpp index f51cc9d51..4d2c64e26 100644 --- a/ctp2_code/ui/aui_ctp2/c3imageformats.cpp +++ b/ctp2_code/ui/aui_ctp2/c3imageformats.cpp @@ -42,8 +42,8 @@ #endif #if defined(__AUI_USE_SDL__) -#include -#include +#include +#include #include "aui_sdlsurface.h" #endif diff --git a/ctp2_code/ui/aui_directx/aui_directui.cpp b/ctp2_code/ui/aui_directx/aui_directui.cpp index e39107f8a..f79ac0c3a 100644 --- a/ctp2_code/ui/aui_directx/aui_directui.cpp +++ b/ctp2_code/ui/aui_directx/aui_directui.cpp @@ -28,7 +28,7 @@ // // - Prevented crashes // - Added graphics DirectX built in double buffering and extended it -// to manual tripple buffering. (1-Jan-2010 Martin Gühmann) +// to manual tripple buffering. (1-Jan-2010 Martin Gühmann) // //---------------------------------------------------------------------------- @@ -43,6 +43,7 @@ #include "aui_joystick.h" #include "aui_directsurface.h" #include "aui_directmouse.h" +#include "aui_directmoviemanager.h" #include "aui_directui.h" @@ -387,4 +388,8 @@ AUI_ERRCODE aui_DirectUI::AltTabIn( void ) return FlushDirtyList(); } +aui_MovieManager* aui_DirectUI::CreateMovieManager( void ) { + return new aui_DirectMovieManager(); +} + #endif // __AUI_USE_DIRECTX__ diff --git a/ctp2_code/ui/aui_directx/aui_directui.h b/ctp2_code/ui/aui_directx/aui_directui.h index c2049ddac..58ca63903 100644 --- a/ctp2_code/ui/aui_directx/aui_directui.h +++ b/ctp2_code/ui/aui_directx/aui_directui.h @@ -79,6 +79,7 @@ class aui_DirectUI : public aui_UI, public aui_DirectX void SetWidth(sint32 width) { m_width = width; } void SetHeight(sint32 height) { m_height = height; } + aui_MovieManager* CreateMovieManager( void ); protected: LPDIRECTDRAWSURFACE m_lpdds; LPDIRECTDRAWSURFACE m_back; diff --git a/ctp2_code/ui/aui_sdl/aui_sdl.cpp b/ctp2_code/ui/aui_sdl/aui_sdl.cpp index f5e2ad497..59efd343e 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdl.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdl.cpp @@ -11,6 +11,31 @@ SDL_Surface *aui_SDL::m_lpdd = 0; uint32 aui_SDL::m_SDLClassId = aui_UniqueId(); sint32 aui_SDL::m_SDLRefCount = 0; +// SKIP_SDL2_EVENT_ISSUES: TODO: handle SDL2 new keyboard-events especially for unicode characters: +// SDL_TEXTEDITING, /**< Keyboard text editing (composition) */ +// SDL_TEXTINPUT, /**< Keyboard text input */ +// SDL_KEYMAPCHANGED /**< Keymap changed due to a system event such as an +// input language or keyboard layout change. +// */ + +int FilterEvents(void* userData, SDL_Event *event) { + switch(event->type) { + // Quit event + case SDL_QUIT: + // Keyboard events + case SDL_KEYDOWN: + case SDL_KEYUP: + // Mouse events + case SDL_MOUSEMOTION: + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + case SDL_MOUSEWHEEL: + return 1; + default: + return 0; + } +} + AUI_ERRCODE aui_SDL::InitCommon(BOOL useExclusiveMode) { m_exclusiveMode = useExclusiveMode; @@ -24,15 +49,8 @@ AUI_ERRCODE aui_SDL::InitCommon(BOOL useExclusiveMode) return AUI_ERRCODE_CREATEFAILED; } */ - SDL_ShowCursor(SDL_DISABLE); - - // enable only a handfull of events - SDL_EventState(SDL_IGNORE, SDL_ALLEVENTS); - SDL_EventState(SDL_ENABLE, SDL_MOUSEEVENTMASK); - SDL_EventState(SDL_ENABLE, SDL_KEYDOWNMASK); - SDL_EventState(SDL_ENABLE, SDL_QUITMASK); - SDL_EnableUNICODE(1); + SDL_SetEventFilter(FilterEvents, NULL); return AUI_ERRCODE_OK; } diff --git a/ctp2_code/ui/aui_sdl/aui_sdl.h b/ctp2_code/ui/aui_sdl/aui_sdl.h index f2173c354..812a25eb4 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdl.h +++ b/ctp2_code/ui/aui_sdl/aui_sdl.h @@ -9,7 +9,7 @@ #if defined(__AUI_USE_SDL__) -#include +#include class aui_SDL { diff --git a/ctp2_code/ui/aui_sdl/aui_sdlblitter.cpp b/ctp2_code/ui/aui_sdl/aui_sdlblitter.cpp index 09ce1be74..94a3901b2 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlblitter.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlblitter.cpp @@ -4,8 +4,8 @@ #include "aui_sdlsurface.h" #include "aui_sdlblitter.h" -#include -#include +#include +#include #ifndef DD_OK #define DD_OK 0 diff --git a/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.cpp b/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.cpp index 9629202cf..b6f0ad482 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.cpp @@ -3,7 +3,7 @@ #if defined(__AUI_USE_SDL__) -#include +#include #include "aui_sdlkeyboard.h" #include "aui_ui.h" #include "c3ui.h" @@ -149,7 +149,7 @@ void aui_SDLKeyboard::convertSDLKeyboardEvent(SDL_KeyboardEvent &sdlevent, (sdlevent.state & SDL_PRESSED) ? TRUE : FALSE, sdlevent.keysym.sym, (sdlevent.keysym.sym>' ' && sdlevent.keysym.sym<127)?sdlevent.keysym.sym:' ');*/ } -uint32 aui_SDLKeyboard::convertSDLKey(SDL_keysym keysym) +uint32 aui_SDLKeyboard::convertSDLKey(SDL_Keysym keysym) { switch (keysym.sym) { case SDLK_ESCAPE: @@ -168,11 +168,9 @@ uint32 aui_SDLKeyboard::convertSDLKey(SDL_keysym keysym) return AUI_KEYBOARD_KEY_LEFTARROW; case SDLK_RIGHT: return AUI_KEYBOARD_KEY_RIGHTARROW; + default: + return AUI_KEYBOARD_KEY_INVALID; } - if ((keysym.unicode & 0xFF80) == 0) { - return (keysym.unicode & 0x7F); - } - return AUI_KEYBOARD_KEY_INVALID; } AUI_ERRCODE aui_SDLKeyboard::Acquire() diff --git a/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.h b/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.h index 6b7235161..65508ec3a 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlkeyboard.h @@ -28,7 +28,7 @@ class aui_SDLKeyboard : public aui_Keyboard, public aui_SDLInput { AUI_ERRCODE createSDLKeyboard(); void convertSDLKeyboardEvent(SDL_KeyboardEvent &sdlevent, aui_KeyboardEvent &auievent); - uint32 convertSDLKey(SDL_keysym keysym); + uint32 convertSDLKey(SDL_Keysym keysym); public: virtual AUI_ERRCODE Acquire(); diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp index 6145567b9..9d09b1a01 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlmouse.cpp @@ -3,6 +3,7 @@ #ifdef __AUI_USE_SDL__ +#include "aui_ui.h" #include "aui_sdlmouse.h" #include "ctp2_listbox.h" @@ -10,8 +11,18 @@ #include "aui_ranger.h" #include "civapp.h" +#include "aui_sdlsurface.h" + +#include "profileDB.h" + extern CivApp *g_civApp; +uint32 HandleMouseAnimation(uint32 interval, void *param) { + aui_SDLMouse *mouse = (aui_SDLMouse*) param; + mouse->HandleAnim(); + return interval; +} + aui_SDLMouse::aui_SDLMouse( AUI_ERRCODE *retval, const MBCHAR *ldlBlock, @@ -19,14 +30,27 @@ aui_SDLMouse::aui_SDLMouse( : aui_Input(), aui_Mouse(retval, ldlBlock), - aui_SDLInput(retval, useExclusiveMode) + aui_SDLInput(retval, useExclusiveMode), + m_currentCursor(NULL), + m_animationTimer(0), + m_lastFrameTick(0) { Assert(AUI_SUCCESS(*retval)); if (!AUI_SUCCESS(*retval)) return; + + int x = 0, y = 0; + SDL_GetMouseState(&x, &y); + m_data.position.x = x; + m_data.position.y = y; } aui_SDLMouse::~aui_SDLMouse() { + if (m_animationTimer) { + SDL_RemoveTimer(m_animationTimer); + m_animationTimer = 0; + } + End(); } void HandleMouseWheel(sint16 delta) @@ -53,63 +77,276 @@ void HandleMouseWheel(sint16 delta) fprintf(stderr, "%s L%d: Mouse wheel for SDL not handled!\n", __FILE__, __LINE__); } -AUI_ERRCODE -aui_SDLMouse::GetInput(void) +AUI_ERRCODE aui_SDLMouse::HandleAnim() { + assert(m_lastIndex > m_firstIndex); + assert(m_curCursor >= m_cursors + m_firstIndex); + + if (m_curCursor++ >= m_cursors + m_lastIndex) { + m_curCursor = m_cursors + m_firstIndex; + } + ActivateCursor(*m_curCursor); + return AUI_ERRCODE_HANDLED; +} + +sint32 aui_SDLMouse::ManipulateInputs(aui_MouseEvent *data, BOOL add) { + assert(!add); + + SDL_PumpEvents(); + + SDL_Event sdlEvents[k_MOUSE_MAXINPUT]; + // check for mouse events + int numberSDLEvents = SDL_PeepEvents(sdlEvents, k_MOUSE_MAXINPUT, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEWHEEL); + if (0 > numberSDLEvents) { + fprintf(stderr, "Mouse PeepEvents failed: %s\n", SDL_GetError()); + return 0; + } + + int numberEvents = 0; + for (int i = 0; i < numberSDLEvents; i++) { + aui_MouseEvent *event = data + numberEvents; + switch (sdlEvents[i].type) { + case SDL_MOUSEMOTION: { + SDL_MouseMotionEvent *motionEvent = &(sdlEvents[i].motion); + event->time = motionEvent->timestamp; + event->position.x = motionEvent->x; + event->position.y = motionEvent->y; + event->lbutton = ((motionEvent->state & SDL_BUTTON_LMASK) != 0); + event->rbutton = ((motionEvent->state & SDL_BUTTON_RMASK) != 0); + numberEvents++; + break; + } + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: { + SDL_MouseButtonEvent *buttonEvent = &(sdlEvents[i].button); + event->time = buttonEvent->timestamp; + event->position.x = buttonEvent->x; + event->position.y = buttonEvent->y; + if (buttonEvent->button == SDL_BUTTON_LEFT) { + event->lbutton = (buttonEvent->state == SDL_PRESSED); + } else if (buttonEvent->button == SDL_BUTTON_RIGHT) { + event->rbutton = (buttonEvent->state == SDL_PRESSED); + } + numberEvents++; + break; + } + case SDL_MOUSEWHEEL: { + if (sdlEvents[i].wheel.y > 0) { + HandleMouseWheel((sint16) 1); + } else if (sdlEvents[i].wheel.y < 0) { + HandleMouseWheel((sint16) -1); + } + break; + } + default: + printf("event not handled: %d\n", sdlEvents[i].type); + break; + } + } + + uint32 currentFrameTick = SDL_GetTicks(); + if (numberEvents) { + m_lastFrameTick = currentFrameTick; + m_data = data[numberEvents - 1]; + } else { + // generate at least a single event every x ticks to force a redraw + const int FRAMES_PER_SECOND = 60; + const int TICKS_PER_FRAME = 1000 / FRAMES_PER_SECOND; + if (currentFrameTick > m_lastFrameTick + TICKS_PER_FRAME) { + m_lastFrameTick = currentFrameTick; + data[0] = m_data; + numberEvents = 1; + } + } + return numberEvents; +} + +void aui_SDLMouse::SetAnimIndexes(sint32 firstIndex, sint32 lastIndex) { + if (firstIndex == m_firstIndex && lastIndex == m_lastIndex) + return; + + if (m_animationTimer) { + SDL_RemoveTimer(m_animationTimer); + m_animationTimer = 0; + } + aui_Mouse::SetAnimIndexes(firstIndex, lastIndex); + if (firstIndex != lastIndex) { + m_animationTimer = SDL_AddTimer(m_animDelay, HandleMouseAnimation, this); + } +} + +void aui_SDLMouse::ActivateCursor(aui_Cursor *cursor) +{ + if (cursor != m_currentCursor) { + aui_Surface *cursorSurface = cursor->TheSurface(); + aui_SDLSurface *sdlCursorSurface = dynamic_cast(cursorSurface); + if (sdlCursorSurface != NULL) { + POINT hotspot; + cursor->GetHotspot(hotspot); + SDL_Cursor *sdlCursor = SDL_CreateColorCursor(sdlCursorSurface->GetSDLSurface(), hotspot.x, hotspot.y); + if (sdlCursor != NULL) { + SDL_Cursor *currentSDLCursor = SDL_GetCursor(); + SDL_SetCursor(sdlCursor); + if (currentSDLCursor) { + SDL_FreeCursor(currentSDLCursor); + } + m_currentCursor = cursor; + } + } + } +} + +AUI_ERRCODE aui_SDLMouse::BltWindowToPrimary(aui_Window *window) +{ + AUI_ERRCODE retcode = AUI_ERRCODE_OK; + + sint32 windowX = window->X(); + sint32 windowY = window->Y(); + aui_Surface *windowSurface = window->TheSurface(); + aui_DirtyList *windowDirtyList = window->GetDirtyList(); + + ListPos position = windowDirtyList->GetHeadPosition(); + for (sint32 j = windowDirtyList->L(); j; j--) + { + RECT *windowDirtyRect = windowDirtyList->GetNext(position); + + RECT screenDirtyRect = *windowDirtyRect; + OffsetRect(&screenDirtyRect, windowX, windowY); + + AUI_ERRCODE errcode = g_ui->BltToSecondary( + screenDirtyRect.left, + screenDirtyRect.top, + windowSurface, + windowDirtyRect, + k_AUI_BLITTER_FLAG_COPY ); + Assert( errcode == AUI_ERRCODE_OK ); + if ( errcode != AUI_ERRCODE_OK ) + { + retcode = AUI_ERRCODE_BLTFAILED; + break; + } + } + + return retcode; +} + +AUI_ERRCODE aui_SDLMouse::BltDirtyRectInfoToPrimary() +{ + AUI_ERRCODE retcode = AUI_ERRCODE_OK; + AUI_ERRCODE errcode; + + if (g_civApp->IsInBackground()) return AUI_ERRCODE_OK; + + tech_WLList *driList = g_ui->GetDirtyRectInfoList(); + + uint32 blitFlags; + LPVOID primaryBuf = NULL; + + if (g_theProfileDB && g_theProfileDB->IsUseDirectXBlitter()) + { + blitFlags = k_AUI_BLITTER_FLAG_COPY; + } + else + { + blitFlags = k_AUI_BLITTER_FLAG_COPY | k_AUI_BLITTER_FLAG_FAST; + errcode = g_ui->Secondary()->Lock(NULL, &primaryBuf, 0); + Assert( errcode == AUI_ERRCODE_OK ); + } + + ListPos position = driList->GetHeadPosition(); + for (sint32 j = driList->L(); j; j--) + { + aui_UI::DirtyRectInfo *dri = driList->GetNext(position); + + aui_Window *window = dri->window; + + sint32 windowX = window->X(); + sint32 windowY = window->Y(); + aui_Surface *windowSurface = window->TheSurface(); + + if (!windowSurface) continue; + + if (g_civApp->IsInBackground()) continue; + + RECT *windowDirtyRect = &dri->rect; + + RECT screenDirtyRect = *windowDirtyRect; + OffsetRect(&screenDirtyRect, windowX, windowY); + + if (!g_civApp->IsInBackground()) // Actual Drawing + { + errcode = g_ui->BltToSecondary( + screenDirtyRect.left, + screenDirtyRect.top, + windowSurface, + windowDirtyRect, + blitFlags); + Assert(errcode == AUI_ERRCODE_OK); + if (errcode != AUI_ERRCODE_OK) + { + retcode = AUI_ERRCODE_BLTFAILED; + break; + } + } + } + + errcode = g_ui->BltSecondaryToPrimary(blitFlags); + Assert(errcode == AUI_ERRCODE_OK); + if (errcode != AUI_ERRCODE_OK) + { + retcode = AUI_ERRCODE_BLTFAILED; + } + + if (!g_theProfileDB || !g_theProfileDB->IsUseDirectXBlitter()) + { + errcode = g_ui->Secondary()->Unlock( primaryBuf ); + Assert( errcode == AUI_ERRCODE_OK ); + } + + return retcode; +} + +AUI_ERRCODE aui_SDLMouse::BltBackgroundColorToPrimary(COLORREF color, aui_DirtyList *colorAreas) +{ + if (g_civApp->IsInBackground()) return AUI_ERRCODE_OK; + + ListPos position = colorAreas->GetHeadPosition(); + for (sint32 j = colorAreas->L(); j; j--) + { + RECT *screenDirtyRect = colorAreas->GetNext(position); + AUI_ERRCODE errcode = g_ui->ColorBltToSecondary(screenDirtyRect, color,0); + Assert(errcode == AUI_ERRCODE_OK); + if (errcode != AUI_ERRCODE_OK) + { + return AUI_ERRCODE_BLTFAILED; + } + } + + return AUI_ERRCODE_OK; +} + +AUI_ERRCODE aui_SDLMouse::BltBackgroundImageToPrimary(aui_Image *image, RECT *imageRect, aui_DirtyList *imageAreas) { - m_data.time = SDL_GetTicks(); - bool haveMoves = false; - SDL_PumpEvents(); - - SDL_Event od[10]; - // check for one of the mouse events - int numElements = - SDL_PeepEvents(od, 10, SDL_GETEVENT, - SDL_EVENTMASK(SDL_MOUSEMOTION) | SDL_EVENTMASK(SDL_MOUSEBUTTONDOWN) | - SDL_EVENTMASK(SDL_MOUSEBUTTONUP)); - if (0 > numElements) { - fprintf(stderr, "Mouse PeepEvents failed: %s\n", SDL_GetError()); - return AUI_ERRCODE_GETDEVICEDATAFAILED; - } - if (0 == numElements) { - if(haveMoves) - return AUI_ERRCODE_OK; - else - return AUI_ERRCODE_NOINPUT; - } - sint32 ev = 0; - while(ev < numElements) { - switch (od[ev].type) { - case SDL_MOUSEMOTION: - m_data.position.x = od[ev].motion.x; - m_data.position.y = od[ev].motion.y; - m_data.lbutton = !!(od[ev].motion.state & SDL_BUTTON_LMASK); - m_data.rbutton = !!(od[ev].motion.state & SDL_BUTTON_RMASK); - break; - case SDL_MOUSEBUTTONDOWN: - case SDL_MOUSEBUTTONUP: - if (od[ev].button.button == SDL_BUTTON_WHEELUP){ - HandleMouseWheel((sint16)1); - break; - } - else if (od[ev].button.button == SDL_BUTTON_WHEELDOWN){ - HandleMouseWheel((sint16)-1); - break; - } - m_data.position.x = od[ev].button.x; - m_data.position.y = od[ev].button.y; - if (od[ev].button.button == SDL_BUTTON_LEFT) { - m_data.lbutton = od[ev].button.state == SDL_PRESSED; - } else if (od[ev].button.button == SDL_BUTTON_RIGHT) { - m_data.rbutton = od[ev].button.state == SDL_PRESSED; - } - break; - default: - printf("event not handeled: %d\n", od[ev].type); - break; - } - ev++; - } - return AUI_ERRCODE_OK; + if (g_civApp->IsInBackground()) return AUI_ERRCODE_OK; + + ListPos position = imageAreas->GetHeadPosition(); + for ( sint32 j = imageAreas->L(); j; j-- ) + { + RECT *screenDirtyRect = imageAreas->GetNext(position); + AUI_ERRCODE errcode = g_ui->BltToSecondary( + screenDirtyRect->left, + screenDirtyRect->top, + image->TheSurface(), + screenDirtyRect, + k_AUI_BLITTER_FLAG_COPY); + + Assert(errcode == AUI_ERRCODE_OK); + if (errcode != AUI_ERRCODE_OK) + { + return AUI_ERRCODE_BLTFAILED; + } + } + + return AUI_ERRCODE_OK; } #endif diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmouse.h b/ctp2_code/ui/aui_sdl/aui_sdlmouse.h index 77d83c36b..bbb99754d 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlmouse.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlmouse.h @@ -15,13 +15,30 @@ class aui_SDLMouse : public aui_Mouse, public aui_SDLInput { public: - aui_SDLMouse(AUI_ERRCODE *retval, const MBCHAR *ldlBlock, - BOOL useExclusiveMode = FALSE); + aui_SDLMouse(AUI_ERRCODE *retval, const MBCHAR *ldlBlock, BOOL useExclusiveMode = FALSE); virtual ~aui_SDLMouse(); + virtual AUI_ERRCODE HandleAnim(); + virtual void SetAnimIndexes(sint32 firstIndex, sint32 lastIndex); + + virtual AUI_ERRCODE BltWindowToPrimary(aui_Window *window); + virtual AUI_ERRCODE BltDirtyRectInfoToPrimary(); + virtual AUI_ERRCODE BltBackgroundColorToPrimary(COLORREF color, aui_DirtyList *colorAreas); + virtual AUI_ERRCODE BltBackgroundImageToPrimary(aui_Image *image, RECT *imageRect, aui_DirtyList *imageAreas); + protected: aui_SDLMouse(); - virtual AUI_ERRCODE GetInput(); + + virtual void ActivateCursor(aui_Cursor *cursor); + + virtual AUI_ERRCODE GetInput() {} + virtual AUI_ERRCODE ReactToInput() {} + virtual sint32 ManipulateInputs(aui_MouseEvent *data, BOOL add); + +private: + aui_Cursor *m_currentCursor; + SDL_TimerID m_animationTimer; + uint32 m_lastFrameTick; }; typedef aui_SDLMouse aui_NativeMouse; diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp new file mode 100644 index 000000000..8d56e1068 --- /dev/null +++ b/ctp2_code/ui/aui_sdl/aui_sdlmovie.cpp @@ -0,0 +1,2225 @@ +// +// The implementation of aui_SDLMovie is a stripped version of ffplay.c. +// ffplay.c is part of ffmpeg (https://github.com/FFmpeg/FFmpeg). +// The version used is 3.4 with some version 4.2 modifications. +// + +#include "c3.h" +#include "aui_sdlmovie.h" + +#if defined(__AUI_USE_SDL__) + +#if defined(USE_SDL_FFMPEG) + +extern "C" { + #include + #include + #include + #include "libswscale/swscale.h" +} +#include +#include "profileDB.h" +#include "aui_sdlsurface.h" + +#define MAX_QUEUE_SIZE (15 * 1024 * 1024) +#define MIN_FRAMES 25 +#define EXTERNAL_CLOCK_MIN_FRAMES 2 +#define EXTERNAL_CLOCK_MAX_FRAMES 10 + +/* Minimum SDL audio buffer size, in samples. */ +#define SDL_AUDIO_MIN_BUFFER_SIZE 512 +/* Calculate actual buffer size keeping in mind not cause too frequent audio callbacks */ +#define SDL_AUDIO_MAX_CALLBACKS_PER_SEC 30 + +/* no AV sync correction is done if below the minimum AV sync threshold */ +#define AV_SYNC_THRESHOLD_MIN 0.04 +/* AV sync correction is done if above the maximum AV sync threshold */ +#define AV_SYNC_THRESHOLD_MAX 0.1 +/* If a frame duration is longer than this, it will not be duplicated to compensate AV sync */ +#define AV_SYNC_FRAMEDUP_THRESHOLD 0.1 +/* no AV correction is done if too big error */ +#define AV_NOSYNC_THRESHOLD 10.0 + +/* maximum audio speed change to get correct sync */ +#define SAMPLE_CORRECTION_PERCENT_MAX 10 + +/* external clock speed adjustment constants for realtime sources based on buffer fullness */ +#define EXTERNAL_CLOCK_SPEED_MIN 0.900 +#define EXTERNAL_CLOCK_SPEED_MAX 1.010 +#define EXTERNAL_CLOCK_SPEED_STEP 0.001 + +/* we use about AUDIO_DIFF_AVG_NB A-V differences to make the average */ +#define AUDIO_DIFF_AVG_NB 20 + +/* polls for possible required screen refresh at least this often, should be less than 1/fps */ +#define REFRESH_RATE 0.01 + +#define CURSOR_HIDE_DELAY 1000000 + +static unsigned sws_flags = SWS_BICUBIC; + +typedef struct MyAVPacketList { + AVPacket pkt; + struct MyAVPacketList *next; + int serial; +} MyAVPacketList; + +typedef struct PacketQueue { + MyAVPacketList *first_pkt, *last_pkt; + int nb_packets; + int size; + int64_t duration; + int abort_request; + int serial; + SDL_mutex *mutex; + SDL_cond *cond; +} PacketQueue; + +#define VIDEO_PICTURE_QUEUE_SIZE 3 +#define SUBPICTURE_QUEUE_SIZE 16 +#define SAMPLE_QUEUE_SIZE 9 +#define FRAME_QUEUE_SIZE FFMAX(SAMPLE_QUEUE_SIZE, FFMAX(VIDEO_PICTURE_QUEUE_SIZE, SUBPICTURE_QUEUE_SIZE)) + +typedef struct AudioParams { + int freq; + int channels; + int64_t channel_layout; + enum AVSampleFormat fmt; + int frame_size; + int bytes_per_sec; +} AudioParams; + +typedef struct Clock { + double pts; /* clock base */ + double pts_drift; /* clock base minus time at which we updated the clock */ + double last_updated; + double speed; + int serial; /* clock is based on a packet with this serial */ + int paused; + int *queue_serial; /* pointer to the current packet queue serial, used for obsolete clock detection */ +} Clock; + +/* Common struct for handling all types of decoded data and allocated render buffers. */ +typedef struct Frame { + AVFrame *frame; + int serial; + double pts; /* presentation timestamp for the frame */ + double duration; /* estimated duration of the frame */ + int64_t pos; /* byte position of the frame in the input file */ + int width; + int height; + int format; + AVRational sar; + int uploaded; + int flip_v; +} Frame; + +typedef struct FrameQueue { + Frame queue[FRAME_QUEUE_SIZE]; + int rindex; + int windex; + int size; + int max_size; + int keep_last; + int rindex_shown; + SDL_mutex *mutex; + SDL_cond *cond; + PacketQueue *pktq; +} FrameQueue; + +enum { + AV_SYNC_AUDIO_MASTER, /* default choice */ + AV_SYNC_VIDEO_MASTER, + AV_SYNC_EXTERNAL_CLOCK, /* synchronize to an external clock */ +}; + +typedef struct Decoder { + AVPacket pkt; + PacketQueue *queue; + AVCodecContext *avctx; + int pkt_serial; + int finished; + int packet_pending; + SDL_cond *empty_queue_cond; + int64_t start_pts; + AVRational start_pts_tb; + int64_t next_pts; + AVRational next_pts_tb; + SDL_Thread *decoder_tid; +} Decoder; + +typedef struct VideoState { + SDL_Thread *read_tid; + int abort_request; + int force_refresh; + int paused; + int last_paused; + int queue_attachments_req; + int read_pause_return; + AVFormatContext *ic; + int realtime; + + Clock audclk; + Clock vidclk; + Clock extclk; + + FrameQueue pictq; + FrameQueue sampq; + + Decoder auddec; + Decoder viddec; + + int audio_stream; + + int av_sync_type; + + double audio_clock; + int audio_clock_serial; + double audio_diff_cum; /* used for AV difference average computation */ + double audio_diff_avg_coef; + double audio_diff_threshold; + int audio_diff_avg_count; + AVStream *audio_st; + PacketQueue audioq; + int audio_hw_buf_size; + uint8_t *audio_buf; + uint8_t *audio_buf1; + unsigned int audio_buf_size; /* in bytes */ + unsigned int audio_buf1_size; + int audio_buf_index; /* in bytes */ + int audio_write_buf_size; + int audio_volume; + int muted; + struct AudioParams audio_src; + struct AudioParams audio_tgt; + struct SwrContext *swr_ctx; + int frame_drops_early; + int frame_drops_late; + + SDL_Texture *vid_texture; + + double frame_timer; + double frame_last_filter_delay; + int video_stream; + AVStream *video_st; + PacketQueue videoq; + double max_frame_duration; // maximum duration of a frame - above this, we consider the jump a timestamp discontinuity + struct SwsContext *img_convert_ctx; + struct SwsContext *sub_convert_ctx; + int eof; + + char *filename; + int width, height, xleft, ytop; + int step; + + SDL_cond *continue_read_thread; +} VideoState; + +/* options specified by the user */ +static int default_width = 640; +static int default_height = 480; +static int screen_width = 0; +static int screen_height = 0; +static int av_sync_type = AV_SYNC_AUDIO_MASTER; +static int infinite_buffer = -1; +static int64_t cursor_last_shown; +static int cursor_hidden = 0; + +/* current context */ +static int is_full_screen; + +static AVPacket flush_pkt; + +static SDL_Renderer *renderer = NULL; +static SDL_Texture *background = NULL; +static SDL_AudioDeviceID audio_dev; + +static const struct TextureFormatEntry { + enum AVPixelFormat format; + int texture_fmt; +} sdl_texture_format_map[] = { + { AV_PIX_FMT_RGB8, SDL_PIXELFORMAT_RGB332 }, + { AV_PIX_FMT_RGB444, SDL_PIXELFORMAT_RGB444 }, + { AV_PIX_FMT_RGB555, SDL_PIXELFORMAT_RGB555 }, + { AV_PIX_FMT_BGR555, SDL_PIXELFORMAT_BGR555 }, + { AV_PIX_FMT_RGB565, SDL_PIXELFORMAT_RGB565 }, + { AV_PIX_FMT_BGR565, SDL_PIXELFORMAT_BGR565 }, + { AV_PIX_FMT_RGB24, SDL_PIXELFORMAT_RGB24 }, + { AV_PIX_FMT_BGR24, SDL_PIXELFORMAT_BGR24 }, + { AV_PIX_FMT_0RGB32, SDL_PIXELFORMAT_RGB888 }, + { AV_PIX_FMT_0BGR32, SDL_PIXELFORMAT_BGR888 }, + { AV_PIX_FMT_NE(RGB0, 0BGR), SDL_PIXELFORMAT_RGBX8888 }, + { AV_PIX_FMT_NE(BGR0, 0RGB), SDL_PIXELFORMAT_BGRX8888 }, + { AV_PIX_FMT_RGB32, SDL_PIXELFORMAT_ARGB8888 }, + { AV_PIX_FMT_RGB32_1, SDL_PIXELFORMAT_RGBA8888 }, + { AV_PIX_FMT_BGR32, SDL_PIXELFORMAT_ABGR8888 }, + { AV_PIX_FMT_BGR32_1, SDL_PIXELFORMAT_BGRA8888 }, + { AV_PIX_FMT_YUV420P, SDL_PIXELFORMAT_IYUV }, + { AV_PIX_FMT_YUYV422, SDL_PIXELFORMAT_YUY2 }, + { AV_PIX_FMT_UYVY422, SDL_PIXELFORMAT_UYVY }, + { AV_PIX_FMT_NONE, SDL_PIXELFORMAT_UNKNOWN }, +}; + +static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt) +{ + MyAVPacketList *pkt1; + + if (q->abort_request) + return -1; + + pkt1 = (MyAVPacketList*) av_malloc(sizeof(MyAVPacketList)); + if (!pkt1) + return -1; + pkt1->pkt = *pkt; + pkt1->next = NULL; + if (pkt == &flush_pkt) + q->serial++; + pkt1->serial = q->serial; + + if (!q->last_pkt) + q->first_pkt = pkt1; + else + q->last_pkt->next = pkt1; + q->last_pkt = pkt1; + q->nb_packets++; + q->size += pkt1->pkt.size + sizeof(*pkt1); + q->duration += pkt1->pkt.duration; + /* XXX: should duplicate packet data in DV case */ + SDL_CondSignal(q->cond); + return 0; +} + +static int packet_queue_put(PacketQueue *q, AVPacket *pkt) +{ + int ret; + + SDL_LockMutex(q->mutex); + ret = packet_queue_put_private(q, pkt); + SDL_UnlockMutex(q->mutex); + + if (pkt != &flush_pkt && ret < 0) + av_packet_unref(pkt); + + return ret; +} + +static int packet_queue_put_nullpacket(PacketQueue *q, int stream_index) +{ + AVPacket pkt1, *pkt = &pkt1; + av_init_packet(pkt); + pkt->data = NULL; + pkt->size = 0; + pkt->stream_index = stream_index; + return packet_queue_put(q, pkt); +} + +/* packet queue handling */ +static int packet_queue_init(PacketQueue *q) +{ + memset(q, 0, sizeof(PacketQueue)); + q->mutex = SDL_CreateMutex(); + if (!q->mutex) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError()); + return AVERROR(ENOMEM); + } + q->cond = SDL_CreateCond(); + if (!q->cond) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError()); + return AVERROR(ENOMEM); + } + q->abort_request = 1; + return 0; +} + +static void packet_queue_flush(PacketQueue *q) +{ + MyAVPacketList *pkt, *pkt1; + + SDL_LockMutex(q->mutex); + for (pkt = q->first_pkt; pkt; pkt = pkt1) { + pkt1 = pkt->next; + av_packet_unref(&pkt->pkt); + av_freep(&pkt); + } + q->last_pkt = NULL; + q->first_pkt = NULL; + q->nb_packets = 0; + q->size = 0; + q->duration = 0; + SDL_UnlockMutex(q->mutex); +} + +static void packet_queue_destroy(PacketQueue *q) +{ + packet_queue_flush(q); + SDL_DestroyMutex(q->mutex); + SDL_DestroyCond(q->cond); +} + +static void packet_queue_abort(PacketQueue *q) +{ + SDL_LockMutex(q->mutex); + + q->abort_request = 1; + + SDL_CondSignal(q->cond); + + SDL_UnlockMutex(q->mutex); +} + +static void packet_queue_start(PacketQueue *q) +{ + SDL_LockMutex(q->mutex); + q->abort_request = 0; + packet_queue_put_private(q, &flush_pkt); + SDL_UnlockMutex(q->mutex); +} + +/* return < 0 if aborted, 0 if no packet and > 0 if packet. */ +static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, int *serial) +{ + MyAVPacketList *pkt1; + int ret; + + SDL_LockMutex(q->mutex); + + for (;;) { + if (q->abort_request) { + ret = -1; + break; + } + + pkt1 = q->first_pkt; + if (pkt1) { + q->first_pkt = pkt1->next; + if (!q->first_pkt) + q->last_pkt = NULL; + q->nb_packets--; + q->size -= pkt1->pkt.size + sizeof(*pkt1); + q->duration -= pkt1->pkt.duration; + *pkt = pkt1->pkt; + if (serial) + *serial = pkt1->serial; + av_free(pkt1); + ret = 1; + break; + } else if (!block) { + ret = 0; + break; + } else { + SDL_CondWait(q->cond, q->mutex); + } + } + SDL_UnlockMutex(q->mutex); + return ret; +} + +static void decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *queue, SDL_cond *empty_queue_cond) { + memset(d, 0, sizeof(Decoder)); + d->avctx = avctx; + d->queue = queue; + d->empty_queue_cond = empty_queue_cond; + d->start_pts = AV_NOPTS_VALUE; + d->pkt_serial = -1; +} + +static int decoder_decode_frame(Decoder *d, AVFrame *frame) { + int ret = AVERROR(EAGAIN); + + for (;;) { + AVPacket pkt; + + if (d->queue->serial == d->pkt_serial) { + do { + if (d->queue->abort_request) + return -1; + + switch (d->avctx->codec_type) { + case AVMEDIA_TYPE_VIDEO: + ret = avcodec_receive_frame(d->avctx, frame); + if (ret >= 0) { + frame->pts = frame->best_effort_timestamp; + } + break; + case AVMEDIA_TYPE_AUDIO: + ret = avcodec_receive_frame(d->avctx, frame); + if (ret >= 0) { + AVRational tb = (AVRational){1, frame->sample_rate}; + if (frame->pts != AV_NOPTS_VALUE) + frame->pts = av_rescale_q(frame->pts, av_codec_get_pkt_timebase(d->avctx), tb); + else if (d->next_pts != AV_NOPTS_VALUE) + frame->pts = av_rescale_q(d->next_pts, d->next_pts_tb, tb); + if (frame->pts != AV_NOPTS_VALUE) { + d->next_pts = frame->pts + frame->nb_samples; + d->next_pts_tb = tb; + } + } + break; + } + if (ret == AVERROR_EOF) { + d->finished = d->pkt_serial; + avcodec_flush_buffers(d->avctx); + return 0; + } + if (ret >= 0) + return 1; + } while (ret != AVERROR(EAGAIN)); + } + + do { + if (d->queue->nb_packets == 0) + SDL_CondSignal(d->empty_queue_cond); + if (d->packet_pending) { + av_packet_move_ref(&pkt, &d->pkt); + d->packet_pending = 0; + } else { + if (packet_queue_get(d->queue, &pkt, 1, &d->pkt_serial) < 0) + return -1; + } + // Added from ffmpeg 4 + if (d->queue->serial == d->pkt_serial) + break; + av_packet_unref(&pkt); + } while (1); + + if (pkt.data == flush_pkt.data) { + avcodec_flush_buffers(d->avctx); + d->finished = 0; + d->next_pts = d->start_pts; + d->next_pts_tb = d->start_pts_tb; + } else { + if (avcodec_send_packet(d->avctx, &pkt) == AVERROR(EAGAIN)) { + av_log(d->avctx, AV_LOG_ERROR, "Receive_frame and send_packet both returned EAGAIN, which is an API violation.\n"); + d->packet_pending = 1; + av_packet_move_ref(&d->pkt, &pkt); + } + av_packet_unref(&pkt); + } + } +} + +static void decoder_destroy(Decoder *d) { + av_packet_unref(&d->pkt); + avcodec_free_context(&d->avctx); +} + +static void frame_queue_unref_item(Frame *vp) +{ + av_frame_unref(vp->frame); +} + +static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_size, int keep_last) +{ + int i; + memset(f, 0, sizeof(FrameQueue)); + if (!(f->mutex = SDL_CreateMutex())) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError()); + return AVERROR(ENOMEM); + } + if (!(f->cond = SDL_CreateCond())) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError()); + return AVERROR(ENOMEM); + } + f->pktq = pktq; + f->max_size = FFMIN(max_size, FRAME_QUEUE_SIZE); + f->keep_last = !!keep_last; + for (i = 0; i < f->max_size; i++) + if (!(f->queue[i].frame = av_frame_alloc())) + return AVERROR(ENOMEM); + return 0; +} + +static void frame_queue_destroy(FrameQueue *f) +{ + int i; + for (i = 0; i < f->max_size; i++) { + Frame *vp = &f->queue[i]; + frame_queue_unref_item(vp); + av_frame_free(&vp->frame); + } + SDL_DestroyMutex(f->mutex); + SDL_DestroyCond(f->cond); +} + +static void frame_queue_signal(FrameQueue *f) +{ + SDL_LockMutex(f->mutex); + SDL_CondSignal(f->cond); + SDL_UnlockMutex(f->mutex); +} + +static Frame *frame_queue_peek(FrameQueue *f) +{ + return &f->queue[(f->rindex + f->rindex_shown) % f->max_size]; +} + +static Frame *frame_queue_peek_next(FrameQueue *f) +{ + return &f->queue[(f->rindex + f->rindex_shown + 1) % f->max_size]; +} + +static Frame *frame_queue_peek_last(FrameQueue *f) +{ + return &f->queue[f->rindex]; +} + +static Frame *frame_queue_peek_writable(FrameQueue *f) +{ + /* wait until we have space to put a new frame */ + SDL_LockMutex(f->mutex); + while (f->size >= f->max_size && + !f->pktq->abort_request) { + SDL_CondWait(f->cond, f->mutex); + } + SDL_UnlockMutex(f->mutex); + + if (f->pktq->abort_request) + return NULL; + + return &f->queue[f->windex]; +} + +static Frame *frame_queue_peek_readable(FrameQueue *f) +{ + /* wait until we have a readable a new frame */ + SDL_LockMutex(f->mutex); + while (f->size - f->rindex_shown <= 0 && + !f->pktq->abort_request) { + SDL_CondWait(f->cond, f->mutex); + } + SDL_UnlockMutex(f->mutex); + + if (f->pktq->abort_request) + return NULL; + + return &f->queue[(f->rindex + f->rindex_shown) % f->max_size]; +} + +static void frame_queue_push(FrameQueue *f) +{ + if (++f->windex == f->max_size) + f->windex = 0; + SDL_LockMutex(f->mutex); + f->size++; + SDL_CondSignal(f->cond); + SDL_UnlockMutex(f->mutex); +} + +static void frame_queue_next(FrameQueue *f) +{ + if (f->keep_last && !f->rindex_shown) { + f->rindex_shown = 1; + return; + } + frame_queue_unref_item(&f->queue[f->rindex]); + if (++f->rindex == f->max_size) + f->rindex = 0; + SDL_LockMutex(f->mutex); + f->size--; + SDL_CondSignal(f->cond); + SDL_UnlockMutex(f->mutex); +} + +/* return the number of undisplayed frames in the queue */ +static int frame_queue_nb_remaining(FrameQueue *f) +{ + return f->size - f->rindex_shown; +} + +static void decoder_abort(Decoder *d, FrameQueue *fq) +{ + packet_queue_abort(d->queue); + frame_queue_signal(fq); + SDL_WaitThread(d->decoder_tid, NULL); + d->decoder_tid = NULL; + packet_queue_flush(d->queue); +} + +static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int new_width, int new_height, SDL_BlendMode blendmode, int init_texture) +{ + Uint32 format; + int access, w, h; + // test on texture added from ffmpeg 4 + if (!*texture || SDL_QueryTexture(*texture, &format, &access, &w, &h) < 0 || new_width != w || new_height != h || new_format != format) { + void *pixels; + int pitch; + if (*texture) + SDL_DestroyTexture(*texture); + if (!(*texture = SDL_CreateTexture(renderer, new_format, SDL_TEXTUREACCESS_STREAMING, new_width, new_height))) + return -1; + if (SDL_SetTextureBlendMode(*texture, blendmode) < 0) + return -1; + if (init_texture) { + if (SDL_LockTexture(*texture, NULL, &pixels, &pitch) < 0) + return -1; + memset(pixels, 0, pitch * new_height); + SDL_UnlockTexture(*texture); + } + av_log(NULL, AV_LOG_VERBOSE, "Created %dx%d texture with %s.\n", new_width, new_height, SDL_GetPixelFormatName(new_format)); + } + return 0; +} + +static void calculate_display_rect(SDL_Rect *rect, + int scr_xleft, int scr_ytop, int scr_width, int scr_height, + int pic_width, int pic_height, AVRational pic_sar) +{ + float aspect_ratio; + int width, height, x, y; + + if (pic_sar.num == 0) + aspect_ratio = 0; + else + aspect_ratio = av_q2d(pic_sar); + + if (aspect_ratio <= 0.0) + aspect_ratio = 1.0; + aspect_ratio *= (float) pic_width / (float) pic_height; + + /* XXX: we suppose the screen has a 1.0 pixel ratio */ + height = scr_height; + width = lrint(height * aspect_ratio) & ~1; + if (width > scr_width) { + width = scr_width; + height = lrint(width / aspect_ratio) & ~1; + } + x = (scr_width - width) / 2; + y = (scr_height - height) / 2; + rect->x = scr_xleft + x; + rect->y = scr_ytop + y; + rect->w = FFMAX(width, 1); + rect->h = FFMAX(height, 1); +} + +static void get_sdl_pix_fmt_and_blendmode(int format, Uint32 *sdl_pix_fmt, SDL_BlendMode *sdl_blendmode) +{ + int i; + *sdl_blendmode = SDL_BLENDMODE_NONE; + *sdl_pix_fmt = SDL_PIXELFORMAT_UNKNOWN; + if (format == AV_PIX_FMT_RGB32 || + format == AV_PIX_FMT_RGB32_1 || + format == AV_PIX_FMT_BGR32 || + format == AV_PIX_FMT_BGR32_1) + *sdl_blendmode = SDL_BLENDMODE_BLEND; + for (i = 0; i < FF_ARRAY_ELEMS(sdl_texture_format_map) - 1; i++) { + if (format == sdl_texture_format_map[i].format) { + *sdl_pix_fmt = sdl_texture_format_map[i].texture_fmt; + return; + } + } +} + +static int upload_texture(SDL_Texture **tex, AVFrame *frame, struct SwsContext **img_convert_ctx) { + int ret = 0; + Uint32 sdl_pix_fmt; + SDL_BlendMode sdl_blendmode; + get_sdl_pix_fmt_and_blendmode(frame->format, &sdl_pix_fmt, &sdl_blendmode); + if (realloc_texture(tex, sdl_pix_fmt == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_ARGB8888 : sdl_pix_fmt, frame->width, frame->height, sdl_blendmode, 0) < 0) + return -1; + switch (sdl_pix_fmt) { + case SDL_PIXELFORMAT_UNKNOWN: + *img_convert_ctx = sws_getCachedContext(*img_convert_ctx, + frame->width, frame->height, (AVPixelFormat) frame->format, frame->width, frame->height, + AV_PIX_FMT_BGRA, sws_flags, NULL, NULL, NULL); + if (*img_convert_ctx != NULL) { + uint8_t *pixels[4]; + int pitch[4]; + if (!SDL_LockTexture(*tex, NULL, (void **)pixels, pitch)) { + sws_scale(*img_convert_ctx, (const uint8_t * const *)frame->data, frame->linesize, + 0, frame->height, pixels, pitch); + SDL_UnlockTexture(*tex); + } + } else { + av_log(NULL, AV_LOG_FATAL, "Cannot initialize the conversion context\n"); + ret = -1; + } + break; + case SDL_PIXELFORMAT_IYUV: + if (frame->linesize[0] > 0 && frame->linesize[1] > 0 && frame->linesize[2] > 0) { + ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0], frame->linesize[0], + frame->data[1], frame->linesize[1], + frame->data[2], frame->linesize[2]); + } else if (frame->linesize[0] < 0 && frame->linesize[1] < 0 && frame->linesize[2] < 0) { + ret = SDL_UpdateYUVTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0], + frame->data[1] + frame->linesize[1] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[1], + frame->data[2] + frame->linesize[2] * (AV_CEIL_RSHIFT(frame->height, 1) - 1), -frame->linesize[2]); + } else { + av_log(NULL, AV_LOG_ERROR, "Mixed negative and positive linesizes are not supported.\n"); + return -1; + } + break; + default: + if (frame->linesize[0] < 0) { + ret = SDL_UpdateTexture(*tex, NULL, frame->data[0] + frame->linesize[0] * (frame->height - 1), -frame->linesize[0]); + } else { + ret = SDL_UpdateTexture(*tex, NULL, frame->data[0], frame->linesize[0]); + } + break; + } + return ret; +} + +static void set_sdl_yuv_conversion_mode(AVFrame *frame) +{ +#if SDL_VERSION_ATLEAST(2,0,8) + SDL_YUV_CONVERSION_MODE mode = SDL_YUV_CONVERSION_AUTOMATIC; + if (frame && (frame->format == AV_PIX_FMT_YUV420P || frame->format == AV_PIX_FMT_YUYV422 || frame->format == AV_PIX_FMT_UYVY422)) { + if (frame->color_range == AVCOL_RANGE_JPEG) + mode = SDL_YUV_CONVERSION_JPEG; + else if (frame->colorspace == AVCOL_SPC_BT709) + mode = SDL_YUV_CONVERSION_BT709; + else if (frame->colorspace == AVCOL_SPC_BT470BG || frame->colorspace == AVCOL_SPC_SMPTE170M || frame->colorspace == AVCOL_SPC_SMPTE240M) + mode = SDL_YUV_CONVERSION_BT601; + } + SDL_SetYUVConversionMode(mode); +#endif +} + +static void video_image_display(VideoState *is) +{ + Frame *vp; + SDL_Rect rect; + + vp = frame_queue_peek_last(&is->pictq); + + calculate_display_rect(&rect, is->xleft, is->ytop, is->width, is->height, vp->width, vp->height, vp->sar); + + if (!vp->uploaded) { + if (upload_texture(&is->vid_texture, vp->frame, &is->img_convert_ctx) < 0) + return; + vp->uploaded = 1; + vp->flip_v = vp->frame->linesize[0] < 0; + } + + // copied from ffmpeg 4 + set_sdl_yuv_conversion_mode(vp->frame); + SDL_RenderCopyEx(renderer, is->vid_texture, NULL, &rect, 0, NULL, (SDL_RendererFlip) (vp->flip_v ? SDL_FLIP_VERTICAL : 0)); + // copied from ffmpeg 4 + set_sdl_yuv_conversion_mode(NULL); +} + +static void stream_component_close(VideoState *is, int stream_index) +{ + AVFormatContext *ic = is->ic; + AVCodecParameters *codecpar; + + if (stream_index < 0 || stream_index >= ic->nb_streams) + return; + codecpar = ic->streams[stream_index]->codecpar; + + switch (codecpar->codec_type) { + case AVMEDIA_TYPE_AUDIO: + decoder_abort(&is->auddec, &is->sampq); + SDL_CloseAudioDevice(audio_dev); + decoder_destroy(&is->auddec); + swr_free(&is->swr_ctx); + av_freep(&is->audio_buf1); + is->audio_buf1_size = 0; + is->audio_buf = NULL; + break; + case AVMEDIA_TYPE_VIDEO: + decoder_abort(&is->viddec, &is->pictq); + decoder_destroy(&is->viddec); + break; + default: + break; + } + + ic->streams[stream_index]->discard = AVDISCARD_ALL; + switch (codecpar->codec_type) { + case AVMEDIA_TYPE_AUDIO: + is->audio_st = NULL; + is->audio_stream = -1; + break; + case AVMEDIA_TYPE_VIDEO: + is->video_st = NULL; + is->video_stream = -1; + break; + default: + break; + } +} + +static void stream_close(VideoState *is) +{ + /* XXX: use a special url_shutdown call to abort parse cleanly */ + is->abort_request = 1; + SDL_WaitThread(is->read_tid, NULL); + + /* close each stream */ + if (is->audio_stream >= 0) + stream_component_close(is, is->audio_stream); + if (is->video_stream >= 0) + stream_component_close(is, is->video_stream); + avformat_close_input(&is->ic); + + packet_queue_destroy(&is->videoq); + packet_queue_destroy(&is->audioq); + + /* free all pictures */ + frame_queue_destroy(&is->pictq); + frame_queue_destroy(&is->sampq); + SDL_DestroyCond(is->continue_read_thread); + sws_freeContext(is->img_convert_ctx); + sws_freeContext(is->sub_convert_ctx); + av_free(is->filename); + if (is->vid_texture) + SDL_DestroyTexture(is->vid_texture); + av_free(is); +} + +static void set_default_window_size(int width, int height, AVRational sar) +{ + SDL_Rect rect; + int max_width = screen_width ? screen_width : INT_MAX; + int max_height = screen_height ? screen_height : INT_MAX; + if (max_width == INT_MAX && max_height == INT_MAX) + max_height = height; + calculate_display_rect(&rect, 0, 0, max_width, max_height, width, height, sar); + default_width = rect.w; + default_height = rect.h; +} + +static int video_open(VideoState *is) +{ + int w,h; + + w = screen_width ? screen_width : default_width; + h = screen_height ? screen_height : default_height; + + is->width = w; + is->height = h; + + return 0; +} + +/* display the current picture, if any */ +static void video_display(VideoState *is) +{ + if (!is->width) + video_open(is); + + SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255); + SDL_RenderClear(renderer); + if (!is_full_screen) { + SDL_RenderCopy(renderer, background, NULL, NULL); + } + if (is->video_st) + video_image_display(is); + SDL_RenderPresent(renderer); +} + +static double get_clock(Clock *c) +{ + if (*c->queue_serial != c->serial) + return NAN; + if (c->paused) { + return c->pts; + } else { + double time = av_gettime_relative() / 1000000.0; + return c->pts_drift + time - (time - c->last_updated) * (1.0 - c->speed); + } +} + +static void set_clock_at(Clock *c, double pts, int serial, double time) +{ + c->pts = pts; + c->last_updated = time; + c->pts_drift = c->pts - time; + c->serial = serial; +} + +static void set_clock(Clock *c, double pts, int serial) +{ + double time = av_gettime_relative() / 1000000.0; + set_clock_at(c, pts, serial, time); +} + +static void set_clock_speed(Clock *c, double speed) +{ + set_clock(c, get_clock(c), c->serial); + c->speed = speed; +} + +static void init_clock(Clock *c, int *queue_serial) +{ + c->speed = 1.0; + c->paused = 0; + c->queue_serial = queue_serial; + set_clock(c, NAN, -1); +} + +static void sync_clock_to_slave(Clock *c, Clock *slave) +{ + double clock = get_clock(c); + double slave_clock = get_clock(slave); + if (!isnan(slave_clock) && (isnan(clock) || fabs(clock - slave_clock) > AV_NOSYNC_THRESHOLD)) + set_clock(c, slave_clock, slave->serial); +} + +static int get_master_sync_type(VideoState *is) { + if (is->av_sync_type == AV_SYNC_VIDEO_MASTER) { + if (is->video_st) + return AV_SYNC_VIDEO_MASTER; + else + return AV_SYNC_AUDIO_MASTER; + } else if (is->av_sync_type == AV_SYNC_AUDIO_MASTER) { + if (is->audio_st) + return AV_SYNC_AUDIO_MASTER; + else + return AV_SYNC_EXTERNAL_CLOCK; + } else { + return AV_SYNC_EXTERNAL_CLOCK; + } +} + +/* get the current master clock value */ +static double get_master_clock(VideoState *is) +{ + double val; + + switch (get_master_sync_type(is)) { + case AV_SYNC_VIDEO_MASTER: + val = get_clock(&is->vidclk); + break; + case AV_SYNC_AUDIO_MASTER: + val = get_clock(&is->audclk); + break; + default: + val = get_clock(&is->extclk); + break; + } + return val; +} + +static void check_external_clock_speed(VideoState *is) { + if (is->video_stream >= 0 && is->videoq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES || + is->audio_stream >= 0 && is->audioq.nb_packets <= EXTERNAL_CLOCK_MIN_FRAMES) { + set_clock_speed(&is->extclk, FFMAX(EXTERNAL_CLOCK_SPEED_MIN, is->extclk.speed - EXTERNAL_CLOCK_SPEED_STEP)); + } else if ((is->video_stream < 0 || is->videoq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES) && + (is->audio_stream < 0 || is->audioq.nb_packets > EXTERNAL_CLOCK_MAX_FRAMES)) { + set_clock_speed(&is->extclk, FFMIN(EXTERNAL_CLOCK_SPEED_MAX, is->extclk.speed + EXTERNAL_CLOCK_SPEED_STEP)); + } else { + double speed = is->extclk.speed; + if (speed != 1.0) + set_clock_speed(&is->extclk, speed + EXTERNAL_CLOCK_SPEED_STEP * (1.0 - speed) / fabs(1.0 - speed)); + } +} + +/* pause or resume the video */ +static void stream_toggle_pause(VideoState *is) +{ + if (is->paused) { + is->frame_timer += av_gettime_relative() / 1000000.0 - is->vidclk.last_updated; + if (is->read_pause_return != AVERROR(ENOSYS)) { + is->vidclk.paused = 0; + } + set_clock(&is->vidclk, get_clock(&is->vidclk), is->vidclk.serial); + } + set_clock(&is->extclk, get_clock(&is->extclk), is->extclk.serial); + is->paused = is->audclk.paused = is->vidclk.paused = is->extclk.paused = !is->paused; +} + +static void toggle_pause(VideoState *is) +{ + stream_toggle_pause(is); + is->step = 0; +} + +static void step_to_next_frame(VideoState *is) +{ + /* if the stream is paused unpause it, then step */ + if (is->paused) + stream_toggle_pause(is); + is->step = 1; +} + +static double compute_target_delay(double delay, VideoState *is) +{ + double sync_threshold, diff = 0; + + /* update delay to follow master synchronisation source */ + if (get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER) { + /* if video is slave, we try to correct big delays by + duplicating or deleting a frame */ + diff = get_clock(&is->vidclk) - get_master_clock(is); + + /* skip or repeat frame. We take into account the + delay to compute the threshold. I still don't know + if it is the best guess */ + sync_threshold = FFMAX(AV_SYNC_THRESHOLD_MIN, FFMIN(AV_SYNC_THRESHOLD_MAX, delay)); + if (!isnan(diff) && fabs(diff) < is->max_frame_duration) { + if (diff <= -sync_threshold) + delay = FFMAX(0, delay + diff); + else if (diff >= sync_threshold && delay > AV_SYNC_FRAMEDUP_THRESHOLD) + delay = delay + diff; + else if (diff >= sync_threshold) + delay = 2 * delay; + } + } + + av_log(NULL, AV_LOG_TRACE, "video: delay=%0.3f A-V=%f\n", + delay, -diff); + + return delay; +} + +static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp) { + if (vp->serial == nextvp->serial) { + double duration = nextvp->pts - vp->pts; + if (isnan(duration) || duration <= 0 || duration > is->max_frame_duration) + return vp->duration; + else + return duration; + } else { + return 0.0; + } +} + +static void update_video_pts(VideoState *is, double pts, int64_t pos, int serial) { + /* update current video pts */ + set_clock(&is->vidclk, pts, serial); + sync_clock_to_slave(&is->extclk, &is->vidclk); +} + +/* called to display each frame */ +static void video_refresh(void *opaque, double *remaining_time) +{ + VideoState *is = (VideoState*) opaque; + double time; + + Frame *sp, *sp2; + + if (!is->paused && get_master_sync_type(is) == AV_SYNC_EXTERNAL_CLOCK && is->realtime) + check_external_clock_speed(is); + + if (is->video_st) { + retry: + if (frame_queue_nb_remaining(&is->pictq) == 0) { + // nothing to do, no picture to display in the queue + } else { + double last_duration, duration, delay; + Frame *vp, *lastvp; + + /* dequeue the picture */ + lastvp = frame_queue_peek_last(&is->pictq); + vp = frame_queue_peek(&is->pictq); + + if (vp->serial != is->videoq.serial) { + frame_queue_next(&is->pictq); + goto retry; + } + + if (lastvp->serial != vp->serial) + is->frame_timer = av_gettime_relative() / 1000000.0; + + if (is->paused) + goto display; + + /* compute nominal last_duration */ + last_duration = vp_duration(is, lastvp, vp); + delay = compute_target_delay(last_duration, is); + + time= av_gettime_relative()/1000000.0; + if (time < is->frame_timer + delay) { + *remaining_time = FFMIN(is->frame_timer + delay - time, *remaining_time); + goto display; + } + + is->frame_timer += delay; + if (delay > 0 && time - is->frame_timer > AV_SYNC_THRESHOLD_MAX) + is->frame_timer = time; + + SDL_LockMutex(is->pictq.mutex); + if (!isnan(vp->pts)) + update_video_pts(is, vp->pts, vp->pos, vp->serial); + SDL_UnlockMutex(is->pictq.mutex); + + if (frame_queue_nb_remaining(&is->pictq) > 1) { + Frame *nextvp = frame_queue_peek_next(&is->pictq); + duration = vp_duration(is, vp, nextvp); + if(!is->step && (get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER) && time > is->frame_timer + duration){ + is->frame_drops_late++; + frame_queue_next(&is->pictq); + goto retry; + } + } + + frame_queue_next(&is->pictq); + is->force_refresh = 1; + + if (is->step && !is->paused) + stream_toggle_pause(is); + } + display: + /* display picture */ + if (is->force_refresh && is->pictq.rindex_shown) + video_display(is); + } + is->force_refresh = 0; +} + +static int queue_picture(VideoState *is, AVFrame *src_frame, double pts, double duration, int64_t pos, int serial) +{ + Frame *vp; + +#if defined(DEBUG_SYNC) + printf("frame_type=%c pts=%0.3f\n", + av_get_picture_type_char(src_frame->pict_type), pts); +#endif + + if (!(vp = frame_queue_peek_writable(&is->pictq))) + return -1; + + vp->sar = src_frame->sample_aspect_ratio; + vp->uploaded = 0; + + vp->width = src_frame->width; + vp->height = src_frame->height; + vp->format = src_frame->format; + + vp->pts = pts; + vp->duration = duration; + vp->pos = pos; + vp->serial = serial; + + set_default_window_size(vp->width, vp->height, vp->sar); + + av_frame_move_ref(vp->frame, src_frame); + frame_queue_push(&is->pictq); + return 0; +} + +static int get_video_frame(VideoState *is, AVFrame *frame) +{ + int got_picture; + + if ((got_picture = decoder_decode_frame(&is->viddec, frame)) < 0) + return -1; + + if (got_picture) { + double dpts = NAN; + + if (frame->pts != AV_NOPTS_VALUE) + dpts = av_q2d(is->video_st->time_base) * frame->pts; + + frame->sample_aspect_ratio = av_guess_sample_aspect_ratio(is->ic, is->video_st, frame); + + if (get_master_sync_type(is) != AV_SYNC_VIDEO_MASTER) { + if (frame->pts != AV_NOPTS_VALUE) { + double diff = dpts - get_master_clock(is); + if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD && + diff - is->frame_last_filter_delay < 0 && + is->viddec.pkt_serial == is->vidclk.serial && + is->videoq.nb_packets) { + is->frame_drops_early++; + av_frame_unref(frame); + got_picture = 0; + } + } + } + } + + return got_picture; +} + +static int audio_thread(void *arg) +{ + VideoState *is = (VideoState*) arg; + AVFrame *frame = av_frame_alloc(); + Frame *af; + int got_frame = 0; + AVRational tb; + int ret = 0; + + if (!frame) + return AVERROR(ENOMEM); + + do { + if ((got_frame = decoder_decode_frame(&is->auddec, frame)) < 0) + goto the_end; + + if (got_frame) { + tb = (AVRational){1, frame->sample_rate}; + + if (!(af = frame_queue_peek_writable(&is->sampq))) + goto the_end; + + af->pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb); + af->pos = frame->pkt_pos; + af->serial = is->auddec.pkt_serial; + af->duration = av_q2d((AVRational){frame->nb_samples, frame->sample_rate}); + + av_frame_move_ref(af->frame, frame); + frame_queue_push(&is->sampq); + } + } while (ret >= 0 || ret == AVERROR(EAGAIN) || ret == AVERROR_EOF); +the_end: + av_frame_free(&frame); + return ret; +} + +static int decoder_start(Decoder *d, int (*fn)(void *), const char *thread_name, void* arg) +{ + packet_queue_start(d->queue); + d->decoder_tid = SDL_CreateThread(fn, thread_name, arg); + if (!d->decoder_tid) { + av_log(NULL, AV_LOG_ERROR, "SDL_CreateThread(): %s\n", SDL_GetError()); + return AVERROR(ENOMEM); + } + return 0; +} + +static int video_thread(void *arg) +{ + VideoState *is = (VideoState*) arg; + AVFrame *frame = av_frame_alloc(); + double pts; + double duration; + int ret; + AVRational tb = is->video_st->time_base; + AVRational frame_rate = av_guess_frame_rate(is->ic, is->video_st, NULL); + + if (!frame) { + return AVERROR(ENOMEM); + } + + for (;;) { + ret = get_video_frame(is, frame); + if (ret < 0) + goto the_end; + if (!ret) + continue; + + duration = (frame_rate.num && frame_rate.den ? av_q2d((AVRational){frame_rate.den, frame_rate.num}) : 0); + pts = (frame->pts == AV_NOPTS_VALUE) ? NAN : frame->pts * av_q2d(tb); + ret = queue_picture(is, frame, pts, duration, frame->pkt_pos, is->viddec.pkt_serial); + av_frame_unref(frame); + + if (ret < 0) + goto the_end; + } + the_end: + av_frame_free(&frame); + return 0; +} + +/* ad-turn the wanted number of samples to get better sync if sync_type is video + * or external master clock */ +static int synchronize_audio(VideoState *is, int nb_samples) +{ + int wanted_nb_samples = nb_samples; + + /* if not master, then we try to remove or add samples to correct the clock */ + if (get_master_sync_type(is) != AV_SYNC_AUDIO_MASTER) { + double diff, avg_diff; + int min_nb_samples, max_nb_samples; + + diff = get_clock(&is->audclk) - get_master_clock(is); + + if (!isnan(diff) && fabs(diff) < AV_NOSYNC_THRESHOLD) { + is->audio_diff_cum = diff + is->audio_diff_avg_coef * is->audio_diff_cum; + if (is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB) { + /* not enough measures to have a correct estimate */ + is->audio_diff_avg_count++; + } else { + /* estimate the A-V difference */ + avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef); + + if (fabs(avg_diff) >= is->audio_diff_threshold) { + wanted_nb_samples = nb_samples + (int)(diff * is->audio_src.freq); + min_nb_samples = ((nb_samples * (100 - SAMPLE_CORRECTION_PERCENT_MAX) / 100)); + max_nb_samples = ((nb_samples * (100 + SAMPLE_CORRECTION_PERCENT_MAX) / 100)); + wanted_nb_samples = av_clip(wanted_nb_samples, min_nb_samples, max_nb_samples); + } + av_log(NULL, AV_LOG_TRACE, "diff=%f adiff=%f sample_diff=%d apts=%0.3f %f\n", + diff, avg_diff, wanted_nb_samples - nb_samples, + is->audio_clock, is->audio_diff_threshold); + } + } else { + /* too big difference : may be initial PTS errors, so + reset A-V filter */ + is->audio_diff_avg_count = 0; + is->audio_diff_cum = 0; + } + } + + return wanted_nb_samples; +} + +/** + * Decode one audio frame and return its uncompressed size. + * + * The processed audio frame is decoded, converted if required, and + * stored in is->audio_buf, with size in bytes given by the return + * value. + */ +static int audio_decode_frame(VideoState *is) +{ + int data_size, resampled_data_size; + int64_t dec_channel_layout; + av_unused double audio_clock0; + int wanted_nb_samples; + Frame *af; + + if (is->paused) + return -1; + + do { + if (!(af = frame_queue_peek_readable(&is->sampq))) + return -1; + frame_queue_next(&is->sampq); + } while (af->serial != is->audioq.serial); + + data_size = av_samples_get_buffer_size(NULL, af->frame->channels, + af->frame->nb_samples, + (AVSampleFormat) af->frame->format, 1); + + dec_channel_layout = + (af->frame->channel_layout && af->frame->channels == av_get_channel_layout_nb_channels(af->frame->channel_layout)) ? + af->frame->channel_layout : av_get_default_channel_layout(af->frame->channels); + wanted_nb_samples = synchronize_audio(is, af->frame->nb_samples); + + if (af->frame->format != is->audio_src.fmt || + dec_channel_layout != is->audio_src.channel_layout || + af->frame->sample_rate != is->audio_src.freq || + (wanted_nb_samples != af->frame->nb_samples && !is->swr_ctx)) { + swr_free(&is->swr_ctx); + is->swr_ctx = swr_alloc_set_opts(NULL, + is->audio_tgt.channel_layout, is->audio_tgt.fmt, is->audio_tgt.freq, + dec_channel_layout, (AVSampleFormat) af->frame->format, af->frame->sample_rate, + 0, NULL); + if (!is->swr_ctx || swr_init(is->swr_ctx) < 0) { + av_log(NULL, AV_LOG_ERROR, + "Cannot create sample rate converter for conversion of %d Hz %s %d channels to %d Hz %s %d channels!\n", + af->frame->sample_rate, av_get_sample_fmt_name((AVSampleFormat) af->frame->format), af->frame->channels, + is->audio_tgt.freq, av_get_sample_fmt_name(is->audio_tgt.fmt), is->audio_tgt.channels); + swr_free(&is->swr_ctx); + return -1; + } + is->audio_src.channel_layout = dec_channel_layout; + is->audio_src.channels = af->frame->channels; + is->audio_src.freq = af->frame->sample_rate; + is->audio_src.fmt = (AVSampleFormat) af->frame->format; + } + + if (is->swr_ctx) { + const uint8_t **in = (const uint8_t **)af->frame->extended_data; + uint8_t **out = &is->audio_buf1; + int out_count = (int64_t)wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate + 256; + int out_size = av_samples_get_buffer_size(NULL, is->audio_tgt.channels, out_count, is->audio_tgt.fmt, 0); + int len2; + if (out_size < 0) { + av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size() failed\n"); + return -1; + } + if (wanted_nb_samples != af->frame->nb_samples) { + if (swr_set_compensation(is->swr_ctx, (wanted_nb_samples - af->frame->nb_samples) * is->audio_tgt.freq / af->frame->sample_rate, + wanted_nb_samples * is->audio_tgt.freq / af->frame->sample_rate) < 0) { + av_log(NULL, AV_LOG_ERROR, "swr_set_compensation() failed\n"); + return -1; + } + } + av_fast_malloc(&is->audio_buf1, &is->audio_buf1_size, out_size); + if (!is->audio_buf1) + return AVERROR(ENOMEM); + len2 = swr_convert(is->swr_ctx, out, out_count, in, af->frame->nb_samples); + if (len2 < 0) { + av_log(NULL, AV_LOG_ERROR, "swr_convert() failed\n"); + return -1; + } + if (len2 == out_count) { + av_log(NULL, AV_LOG_WARNING, "audio buffer is probably too small\n"); + if (swr_init(is->swr_ctx) < 0) + swr_free(&is->swr_ctx); + } + is->audio_buf = is->audio_buf1; + resampled_data_size = len2 * is->audio_tgt.channels * av_get_bytes_per_sample(is->audio_tgt.fmt); + } else { + is->audio_buf = af->frame->data[0]; + resampled_data_size = data_size; + } + + audio_clock0 = is->audio_clock; + /* update the audio clock with the pts */ + if (!isnan(af->pts)) + is->audio_clock = af->pts + (double) af->frame->nb_samples / af->frame->sample_rate; + else + is->audio_clock = NAN; + is->audio_clock_serial = af->serial; +#ifdef DEBUG + { + static double last_clock; + printf("audio: delay=%0.3f clock=%0.3f clock0=%0.3f\n", + is->audio_clock - last_clock, + is->audio_clock, audio_clock0); + last_clock = is->audio_clock; + } +#endif + return resampled_data_size; +} + +/* prepare a new audio buffer */ +static void sdl_audio_callback(void *opaque, Uint8 *stream, int len) +{ + VideoState *is = (VideoState*) opaque; + int audio_size, len1; + + int64_t audio_callback_time = av_gettime_relative(); + + while (len > 0) { + if (is->audio_buf_index >= is->audio_buf_size) { + audio_size = audio_decode_frame(is); + if (audio_size < 0) { + /* if error, just output silence */ + is->audio_buf = NULL; + is->audio_buf_size = SDL_AUDIO_MIN_BUFFER_SIZE / is->audio_tgt.frame_size * is->audio_tgt.frame_size; + } else { + is->audio_buf_size = audio_size; + } + is->audio_buf_index = 0; + } + len1 = is->audio_buf_size - is->audio_buf_index; + if (len1 > len) + len1 = len; + if (!is->muted && is->audio_buf && is->audio_volume == SDL_MIX_MAXVOLUME) + memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1); + else { + memset(stream, 0, len1); + if (!is->muted && is->audio_buf) + SDL_MixAudioFormat(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, AUDIO_S16SYS, len1, is->audio_volume); + } + len -= len1; + stream += len1; + is->audio_buf_index += len1; + } + is->audio_write_buf_size = is->audio_buf_size - is->audio_buf_index; + /* Let's assume the audio driver that is used by SDL has two periods. */ + if (!isnan(is->audio_clock)) { + set_clock_at(&is->audclk, is->audio_clock - (double)(2 * is->audio_hw_buf_size + is->audio_write_buf_size) / is->audio_tgt.bytes_per_sec, is->audio_clock_serial, audio_callback_time / 1000000.0); + sync_clock_to_slave(&is->extclk, &is->audclk); + } +} + +static int audio_open(void *opaque, int64_t wanted_channel_layout, int wanted_nb_channels, int wanted_sample_rate, struct AudioParams *audio_hw_params) +{ + SDL_AudioSpec wanted_spec, spec; + const char *env; + static const int next_nb_channels[] = {0, 0, 1, 6, 2, 6, 4, 6}; + static const int next_sample_rates[] = {0, 44100, 48000, 96000, 192000}; + int next_sample_rate_idx = FF_ARRAY_ELEMS(next_sample_rates) - 1; + + env = SDL_getenv("SDL_AUDIO_CHANNELS"); + if (env) { + wanted_nb_channels = atoi(env); + wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels); + } + if (!wanted_channel_layout || wanted_nb_channels != av_get_channel_layout_nb_channels(wanted_channel_layout)) { + wanted_channel_layout = av_get_default_channel_layout(wanted_nb_channels); + wanted_channel_layout &= ~AV_CH_LAYOUT_STEREO_DOWNMIX; + } + wanted_nb_channels = av_get_channel_layout_nb_channels(wanted_channel_layout); + wanted_spec.channels = wanted_nb_channels; + wanted_spec.freq = wanted_sample_rate; + if (wanted_spec.freq <= 0 || wanted_spec.channels <= 0) { + av_log(NULL, AV_LOG_ERROR, "Invalid sample rate or channel count!\n"); + return -1; + } + while (next_sample_rate_idx && next_sample_rates[next_sample_rate_idx] >= wanted_spec.freq) + next_sample_rate_idx--; + wanted_spec.format = AUDIO_S16SYS; + wanted_spec.silence = 0; + wanted_spec.samples = FFMAX(SDL_AUDIO_MIN_BUFFER_SIZE, 2 << av_log2(wanted_spec.freq / SDL_AUDIO_MAX_CALLBACKS_PER_SEC)); + wanted_spec.callback = sdl_audio_callback; + wanted_spec.userdata = opaque; + while (!(audio_dev = SDL_OpenAudioDevice(NULL, 0, &wanted_spec, &spec, SDL_AUDIO_ALLOW_FREQUENCY_CHANGE | SDL_AUDIO_ALLOW_CHANNELS_CHANGE))) { + av_log(NULL, AV_LOG_WARNING, "SDL_OpenAudio (%d channels, %d Hz): %s\n", + wanted_spec.channels, wanted_spec.freq, SDL_GetError()); + wanted_spec.channels = next_nb_channels[FFMIN(7, wanted_spec.channels)]; + if (!wanted_spec.channels) { + wanted_spec.freq = next_sample_rates[next_sample_rate_idx--]; + wanted_spec.channels = wanted_nb_channels; + if (!wanted_spec.freq) { + av_log(NULL, AV_LOG_ERROR, + "No more combinations to try, audio open failed\n"); + return -1; + } + } + wanted_channel_layout = av_get_default_channel_layout(wanted_spec.channels); + } + if (spec.format != AUDIO_S16SYS) { + av_log(NULL, AV_LOG_ERROR, + "SDL advised audio format %d is not supported!\n", spec.format); + return -1; + } + if (spec.channels != wanted_spec.channels) { + wanted_channel_layout = av_get_default_channel_layout(spec.channels); + if (!wanted_channel_layout) { + av_log(NULL, AV_LOG_ERROR, + "SDL advised channel count %d is not supported!\n", spec.channels); + return -1; + } + } + + audio_hw_params->fmt = AV_SAMPLE_FMT_S16; + audio_hw_params->freq = spec.freq; + audio_hw_params->channel_layout = wanted_channel_layout; + audio_hw_params->channels = spec.channels; + audio_hw_params->frame_size = av_samples_get_buffer_size(NULL, audio_hw_params->channels, 1, audio_hw_params->fmt, 1); + audio_hw_params->bytes_per_sec = av_samples_get_buffer_size(NULL, audio_hw_params->channels, audio_hw_params->freq, audio_hw_params->fmt, 1); + if (audio_hw_params->bytes_per_sec <= 0 || audio_hw_params->frame_size <= 0) { + av_log(NULL, AV_LOG_ERROR, "av_samples_get_buffer_size failed\n"); + return -1; + } + return spec.size; +} + +/* open a given stream. Return 0 if OK */ +static int stream_component_open(VideoState *is, int stream_index) +{ + AVFormatContext *ic = is->ic; + AVCodecContext *avctx; + AVCodec *codec; + AVDictionary *opts = NULL; + AVDictionaryEntry *t = NULL; + int sample_rate, nb_channels; + int64_t channel_layout; + int ret = 0; + + if (stream_index < 0 || stream_index >= ic->nb_streams) + return -1; + + avctx = avcodec_alloc_context3(NULL); + if (!avctx) + return AVERROR(ENOMEM); + + ret = avcodec_parameters_to_context(avctx, ic->streams[stream_index]->codecpar); + if (ret < 0) + goto fail; + av_codec_set_pkt_timebase(avctx, ic->streams[stream_index]->time_base); + + codec = avcodec_find_decoder(avctx->codec_id); + + if (!codec) { + av_log(NULL, AV_LOG_WARNING, + "No codec could be found with id %d\n", avctx->codec_id); + ret = AVERROR(EINVAL); + goto fail; + } + + avctx->codec_id = codec->id; +#if FF_API_EMU_EDGE + if(codec->capabilities & AV_CODEC_CAP_DR1) + avctx->flags |= CODEC_FLAG_EMU_EDGE; +#endif + + if ((ret = avcodec_open2(avctx, codec, NULL)) < 0) { + goto fail; + } + + is->eof = 0; + ic->streams[stream_index]->discard = AVDISCARD_DEFAULT; + switch (avctx->codec_type) { + case AVMEDIA_TYPE_AUDIO: + sample_rate = avctx->sample_rate; + nb_channels = avctx->channels; + channel_layout = avctx->channel_layout; + + /* prepare audio output */ + if ((ret = audio_open(is, channel_layout, nb_channels, sample_rate, &is->audio_tgt)) < 0) + goto fail; + is->audio_hw_buf_size = ret; + is->audio_src = is->audio_tgt; + is->audio_buf_size = 0; + is->audio_buf_index = 0; + + /* init averaging filter */ + is->audio_diff_avg_coef = exp(log(0.01) / AUDIO_DIFF_AVG_NB); + is->audio_diff_avg_count = 0; + /* since we do not have a precise anough audio FIFO fullness, + we correct audio sync only if larger than this threshold */ + is->audio_diff_threshold = (double)(is->audio_hw_buf_size) / is->audio_tgt.bytes_per_sec; + + is->audio_stream = stream_index; + is->audio_st = ic->streams[stream_index]; + + decoder_init(&is->auddec, avctx, &is->audioq, is->continue_read_thread); + if ((is->ic->iformat->flags & (AVFMT_NOBINSEARCH | AVFMT_NOGENSEARCH | AVFMT_NO_BYTE_SEEK)) && !is->ic->iformat->read_seek) { + is->auddec.start_pts = is->audio_st->start_time; + is->auddec.start_pts_tb = is->audio_st->time_base; + } + if ((ret = decoder_start(&is->auddec, audio_thread, "audio_decoder", is)) < 0) + goto out; + SDL_PauseAudioDevice(audio_dev, 0); + break; + case AVMEDIA_TYPE_VIDEO: + is->video_stream = stream_index; + is->video_st = ic->streams[stream_index]; + + decoder_init(&is->viddec, avctx, &is->videoq, is->continue_read_thread); + if ((ret = decoder_start(&is->viddec, video_thread, "video_decoder", is)) < 0) + goto out; + is->queue_attachments_req = 1; + break; + default: + break; + } + goto out; + +fail: + avcodec_free_context(&avctx); +out: + av_dict_free(&opts); + + return ret; +} + +static int decode_interrupt_cb(void *ctx) +{ + VideoState *is = (VideoState*) ctx; + return is->abort_request; +} + +static int stream_has_enough_packets(AVStream *st, int stream_id, PacketQueue *queue) { + return stream_id < 0 || + queue->abort_request || + (st->disposition & AV_DISPOSITION_ATTACHED_PIC) || + queue->nb_packets > MIN_FRAMES && (!queue->duration || av_q2d(st->time_base) * queue->duration > 1.0); +} + +static int is_realtime(AVFormatContext *s) +{ + if( !strcmp(s->iformat->name, "rtp") + || !strcmp(s->iformat->name, "rtsp") + || !strcmp(s->iformat->name, "sdp") + ) + return 1; + + if(s->pb && ( !strncmp(s->filename, "rtp:", 4) + || !strncmp(s->filename, "udp:", 4) + ) + ) + return 1; + return 0; +} + +void print_error(const char *filename, int err) +{ + char errbuf[128]; + const char *errbuf_ptr = errbuf; + + if (av_strerror(err, errbuf, sizeof(errbuf)) < 0) + errbuf_ptr = strerror(AVUNERROR(err)); + av_log(NULL, AV_LOG_ERROR, "%s: %s\n", filename, errbuf_ptr); +} + +/* this thread gets the stream from the disk or the network */ +static int read_thread(void *arg) +{ + VideoState *is = (VideoState*)arg; + AVFormatContext *ic = NULL; + int err, i, ret; + int st_index[AVMEDIA_TYPE_NB]; + AVPacket pkt1, *pkt = &pkt1; + int64_t stream_start_time; + AVDictionaryEntry *t; + SDL_mutex *wait_mutex = SDL_CreateMutex(); + int scan_all_pmts_set = 0; + int64_t pkt_ts; + + if (!wait_mutex) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError()); + ret = AVERROR(ENOMEM); + goto fail; + } + + memset(st_index, -1, sizeof(st_index)); + is->video_stream = -1; + is->audio_stream = -1; + is->eof = 0; + + ic = avformat_alloc_context(); + if (!ic) { + av_log(NULL, AV_LOG_FATAL, "Could not allocate context.\n"); + ret = AVERROR(ENOMEM); + goto fail; + } + ic->interrupt_callback.callback = decode_interrupt_cb; + ic->interrupt_callback.opaque = is; + + err = avformat_open_input(&ic, is->filename, NULL, NULL); + if (err < 0) { + print_error(is->filename, err); + ret = -1; + goto fail; + } + is->ic = ic; + + av_format_inject_global_side_data(ic); + + if (ic->pb) + ic->pb->eof_reached = 0; + + is->max_frame_duration = (ic->iformat->flags & AVFMT_TS_DISCONT) ? 10.0 : 3600.0; + + is->realtime = is_realtime(ic); + + st_index[AVMEDIA_TYPE_VIDEO] = + av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO, + st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0); + st_index[AVMEDIA_TYPE_AUDIO] = + av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO, + st_index[AVMEDIA_TYPE_AUDIO], + st_index[AVMEDIA_TYPE_VIDEO], + NULL, 0); + if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) { + AVStream *st = ic->streams[st_index[AVMEDIA_TYPE_VIDEO]]; + AVCodecParameters *codecpar = st->codecpar; + AVRational sar = av_guess_sample_aspect_ratio(ic, st, NULL); + if (codecpar->width) + set_default_window_size(codecpar->width, codecpar->height, sar); + } + + /* open the streams */ + if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) { + stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]); + } + + ret = -1; + if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) { + ret = stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]); + } + + if (is->video_stream < 0 && is->audio_stream < 0) { + av_log(NULL, AV_LOG_FATAL, "Failed to open file '%s' or configure filtergraph\n", + is->filename); + ret = -1; + goto fail; + } + + if (infinite_buffer < 0 && is->realtime) + infinite_buffer = 1; + + for (;;) { + if (is->abort_request) + break; + if (is->paused != is->last_paused) { + is->last_paused = is->paused; + if (is->paused) + is->read_pause_return = av_read_pause(ic); + else + av_read_play(ic); + } + if (is->queue_attachments_req) { + if (is->video_st && is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC) { + AVPacket copy = { 0 }; + if ((ret = av_packet_ref(©, &is->video_st->attached_pic)) < 0) + goto fail; + packet_queue_put(&is->videoq, ©); + packet_queue_put_nullpacket(&is->videoq, is->video_stream); + } + is->queue_attachments_req = 0; + } + + /* if the queue are full, no need to read more */ + if (infinite_buffer<1 && + (is->audioq.size + is->videoq.size > MAX_QUEUE_SIZE + || (stream_has_enough_packets(is->audio_st, is->audio_stream, &is->audioq) && + stream_has_enough_packets(is->video_st, is->video_stream, &is->videoq)))) { + /* wait 10 ms */ + SDL_LockMutex(wait_mutex); + SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10); + SDL_UnlockMutex(wait_mutex); + continue; + } + if (!is->paused && + (!is->audio_st || (is->auddec.finished == is->audioq.serial && frame_queue_nb_remaining(&is->sampq) == 0)) && + (!is->video_st || (is->viddec.finished == is->videoq.serial && frame_queue_nb_remaining(&is->pictq) == 0))) { + ret = AVERROR_EOF; + goto fail; + } + ret = av_read_frame(ic, pkt); + if (ret < 0) { + if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !is->eof) { + if (is->video_stream >= 0) + packet_queue_put_nullpacket(&is->videoq, is->video_stream); + if (is->audio_stream >= 0) + packet_queue_put_nullpacket(&is->audioq, is->audio_stream); + is->eof = 1; + } + if (ic->pb && ic->pb->error) + break; + SDL_LockMutex(wait_mutex); + SDL_CondWaitTimeout(is->continue_read_thread, wait_mutex, 10); + SDL_UnlockMutex(wait_mutex); + continue; + } else { + is->eof = 0; + } + /* check if packet is in play range specified by user, then queue, otherwise discard */ + stream_start_time = ic->streams[pkt->stream_index]->start_time; + pkt_ts = pkt->pts == AV_NOPTS_VALUE ? pkt->dts : pkt->pts; + if (pkt->stream_index == is->audio_stream) { + packet_queue_put(&is->audioq, pkt); + } else if (pkt->stream_index == is->video_stream + && !(is->video_st->disposition & AV_DISPOSITION_ATTACHED_PIC)) { + packet_queue_put(&is->videoq, pkt); + } else { + av_packet_unref(pkt); + } + } + + ret = 0; +fail: + if (ic && !is->ic) + avformat_close_input(&ic); + + if (ret != 0) { + SDL_Event event; + event.type = SDL_QUIT; + SDL_PushEvent(&event); + } + SDL_DestroyMutex(wait_mutex); + return 0; +} + +static VideoState *stream_open(const char *filename, int startup_volume) +{ + VideoState *is; + + is = (VideoState *) av_mallocz(sizeof(VideoState)); + if (!is) + return NULL; + is->filename = av_strdup(filename); + if (!is->filename) + goto fail; + is->ytop = 0; + is->xleft = 0; + + /* start video display */ + if (frame_queue_init(&is->pictq, &is->videoq, VIDEO_PICTURE_QUEUE_SIZE, 1) < 0) + goto fail; + if (frame_queue_init(&is->sampq, &is->audioq, SAMPLE_QUEUE_SIZE, 1) < 0) + goto fail; + + if (packet_queue_init(&is->videoq) < 0 || + packet_queue_init(&is->audioq) < 0) + goto fail; + + if (!(is->continue_read_thread = SDL_CreateCond())) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateCond(): %s\n", SDL_GetError()); + goto fail; + } + + init_clock(&is->vidclk, &is->videoq.serial); + init_clock(&is->audclk, &is->audioq.serial); + init_clock(&is->extclk, &is->extclk.serial); + is->audio_clock_serial = -1; + if (startup_volume < 0) + av_log(NULL, AV_LOG_WARNING, "-volume=%d < 0, setting to 0\n", startup_volume); + if (startup_volume > 100) + av_log(NULL, AV_LOG_WARNING, "-volume=%d > 100, setting to 100\n", startup_volume); + startup_volume = av_clip(startup_volume, 0, 100); + startup_volume = av_clip(SDL_MIX_MAXVOLUME * startup_volume / 100, 0, SDL_MIX_MAXVOLUME); + is->audio_volume = startup_volume; + is->muted = 0; + is->av_sync_type = av_sync_type; + return is; +fail: + stream_close(is); + return NULL; + +} + +static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) { + double remaining_time = 0.0; + SDL_PumpEvents(); + while (!SDL_PeepEvents(event, 1, SDL_GETEVENT, SDL_FIRSTEVENT, SDL_LASTEVENT)) { + if (is_full_screen && !cursor_hidden && av_gettime_relative() - cursor_last_shown > CURSOR_HIDE_DELAY) { + SDL_ShowCursor(0); + cursor_hidden = 1; + } + if (remaining_time > 0.0) + av_usleep((int64_t)(remaining_time * 1000000.0)); + remaining_time = REFRESH_RATE; + if (!is->paused || is->force_refresh) + video_refresh(is, &remaining_time); + SDL_PumpEvents(); + } +} + +#else // USE_SDL_FFMPEG + +struct VideoState { +}; + +#endif // USE_SDL_FFMPEG + +aui_SDLMovie::aui_SDLMovie(AUI_ERRCODE *retval, const MBCHAR * filename) : + aui_Movie(), + m_videoState(NULL), + m_renderer(NULL), + m_background(NULL), + m_windowWidth(0), + m_windowHeight(0), + m_logicalWidth(0), + m_logicalHeight(0) +{ + strncpy(m_filename, filename, sizeof(m_filename)); + m_filename[MAX_PATH] = '\0'; + *retval = AUI_ERRCODE_OK; +} + +aui_SDLMovie::~aui_SDLMovie() { + Assert(!m_videoState); + m_renderer = NULL; + m_background = NULL; +} + +void aui_SDLMovie::SetContext(SDL_Renderer *renderer, SDL_Texture *background, const int windowWidth, + const int windowHeight) { + Assert(renderer); + Assert(background); + m_renderer = renderer; + m_background = background; + m_windowWidth = windowWidth; + m_windowHeight = windowHeight; +} + +AUI_ERRCODE aui_SDLMovie::Load() { + return AUI_ERRCODE_OK; +} + +AUI_ERRCODE aui_SDLMovie::Unload() { + return Close(); +} + +AUI_ERRCODE aui_SDLMovie::Open(uint32 flags, aui_Surface *surface, RECT *rect) { + +#if defined(USE_SDL_FFMPEG) + if (!m_renderer || (!(flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN) && !m_background)) { + return AUI_ERRCODE_MOVIEFAILED; + } + + static SDL_RendererInfo renderer_info = {0}; + SDL_GetRendererInfo(m_renderer, &renderer_info); + if (!renderer_info.num_texture_formats) { + av_log(NULL, AV_LOG_FATAL, "Failed to create window or renderer: %s", SDL_GetError()); + Close(); + return AUI_ERRCODE_MOVIEFAILED; + } + + m_flags = flags; + renderer = m_renderer; + + av_init_packet(&flush_pkt); + flush_pkt.data = (uint8_t *)&flush_pkt; + + is_full_screen = m_flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN; + SDL_RenderGetLogicalSize(renderer, &m_logicalWidth, &m_logicalHeight); + if (is_full_screen) { + screen_width = m_windowWidth; + screen_height = m_windowHeight; + SDL_RenderSetLogicalSize(renderer, m_windowWidth, m_windowHeight); + } else { + screen_width = rect->right - rect->left; + screen_height = rect->bottom - rect->top; + background = m_background; + } + + // Adjust volume range ctp2 [0..10] -> ffmpeg [0..100] + m_videoState = stream_open(m_filename, g_theProfileDB->GetSFXVolume() * 10); + if (m_videoState && !(m_flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN)) { + m_videoState->xleft = rect->left; + m_videoState->ytop = rect->top; + } + return m_videoState ? AUI_ERRCODE_OK : AUI_ERRCODE_MOVIEFAILED; +#else // USE_SDL_FFMPEG + return AUI_ERRCODE_OK; +#endif // USE_SDL_FFMPEG +} + +AUI_ERRCODE aui_SDLMovie::Close() { + +#if defined(USE_SDL_FFMPEG) + SDL_ShowCursor(SDL_ENABLE); + if (m_videoState) { + Stop(); + if (m_flags & k_AUI_MOVIE_PLAYFLAG_PLAYANDHOLD) { + GrabLastFrame(); + } + stream_close(m_videoState); + m_videoState = NULL; + } + + if (m_flags & k_AUI_MOVIE_PLAYFLAG_ONSCREEN) { + SDL_RenderSetLogicalSize(m_renderer, m_logicalWidth, m_logicalHeight); + } + renderer = NULL; + background = NULL; + m_flags = 0; + m_isFinished = TRUE; +#endif // USE_SDL_FFMPEG + return AUI_ERRCODE_OK; +} + +AUI_ERRCODE aui_SDLMovie::Play() { + +#if defined(USE_SDL_FFMPEG) + if (m_videoState) { + m_videoState->read_tid = SDL_CreateThread(read_thread, "read_thread", m_videoState); + if (!m_videoState->read_tid) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateThread(): %s\n", SDL_GetError()); + Stop(); + return AUI_ERRCODE_MOVIEFAILED; + } + } +#endif // USE_SDL_FFMPEG + return AUI_ERRCODE_OK; +} + +AUI_ERRCODE aui_SDLMovie::Stop() { + return AUI_ERRCODE_OK; +} + +AUI_ERRCODE aui_SDLMovie::Pause() { + +#if defined(USE_SDL_FFMPEG) + if (m_videoState && !m_videoState->paused) { + toggle_pause(m_videoState); + } +#endif // USE_SDL_FFMPEG + return AUI_ERRCODE_OK; +} + +AUI_ERRCODE aui_SDLMovie::Resume() { + +#if defined(USE_SDL_FFMPEG) + if (m_videoState && m_videoState->paused) { + toggle_pause(m_videoState); + } +#endif // USE_SDL_FFMPEG +} + +AUI_ERRCODE aui_SDLMovie::Process() { + +#if defined(USE_SDL_FFMPEG) + if (m_videoState) { + /* handle an event sent by the GUI */ + SDL_Event event; + + bool movieFinished = false; + while (!movieFinished) { + refresh_loop_wait_event(m_videoState, &event); + movieFinished = HandleMovieEvent(event); + } + Close(); + } +#endif // USE_SDL_FFMPEG +} + +BOOL aui_SDLMovie::IsOpen() const { + return m_videoState != NULL || m_isFinished; +} + +BOOL aui_SDLMovie::IsPlaying() const { +#if defined(USE_SDL_FFMPEG) + return m_videoState && m_videoState->read_tid; +#else // USE_SDL_FFMPEG + return FALSE; +#endif // USE_SDL_FFMPEG +} + +BOOL aui_SDLMovie::IsPaused() const { + +#if defined(USE_SDL_FFMPEG) + return m_videoState && m_videoState->paused; +#else // USE_SDL_FFMPEG + return FALSE; +#endif // USE_SDL_FFMPEG +} + +bool aui_SDLMovie::HandleMovieEvent(SDL_Event &event) { + bool movieFinished = false; + + switch (event.type) { + case SDL_QUIT: + movieFinished = true; + break; + case SDL_KEYDOWN: + switch (event.key.keysym.sym) { + case SDLK_ESCAPE: + case SDLK_SPACE: + case SDLK_q: + movieFinished = true; + break; + case SDLK_p: + toggle_pause(m_videoState); + break; + default: + break; + } + break; + case SDL_MOUSEMOTION: + if (cursor_hidden) { + SDL_ShowCursor(1); + cursor_hidden = 0; + } else { + if ((event.motion.type & SDL_BUTTON_LMASK != 0) && + (is_full_screen || InsideMovieArea(event.button.x, event.button.y))) { + movieFinished = true; + } + } + cursor_last_shown = av_gettime_relative(); + break; + case SDL_MOUSEBUTTONDOWN: + case SDL_MOUSEBUTTONUP: + if (is_full_screen || InsideMovieArea(event.button.x, event.button.y)) { + movieFinished = true; + } + break; + default: + break; + } + return movieFinished; +} + + +bool aui_SDLMovie::InsideMovieArea(int x, int y) { + return (x > m_videoState->xleft && x < (m_videoState->xleft + m_videoState->width) + && y > m_videoState->ytop && y < (m_videoState->ytop + m_videoState->height)); +} + +void aui_SDLMovie::GrabLastFrame() { + aui_SDLSurface *sdlSurface = dynamic_cast(GetDestSurface()); + if (sdlSurface) { + // Undo logical size if needed; to grab unscaled pixels + if (m_windowWidth != m_logicalWidth) { + SDL_RenderSetLogicalSize(m_renderer, m_windowWidth, m_windowHeight); + } + + SDL_Surface *surface = sdlSurface->GetSDLSurface(); + SDL_Texture *backgroundTexture = SDL_CreateTextureFromSurface(m_renderer, surface); + if (backgroundTexture) { + SDL_RenderClear(m_renderer); + + SDL_Rect surfaceRect = { 0, 0, surface->w, surface->h }; + SDL_RenderCopy(m_renderer, backgroundTexture, NULL, &surfaceRect); + + RECT *destRect = GetDestRect(); + SDL_Rect sdlSrcRect = {0, 0, destRect->right - destRect->left, destRect->bottom - destRect->top }; + SDL_Rect sdlDestRect = { destRect->left, destRect->top, sdlSrcRect.w, sdlSrcRect.h }; + SDL_RenderCopy(m_renderer, m_videoState->vid_texture, &sdlSrcRect, &sdlDestRect); + SDL_RenderReadPixels(m_renderer, &surfaceRect, surface->format->format, surface->pixels, surface->pitch); + + SDL_RenderClear(m_renderer); + SDL_DestroyTexture(backgroundTexture); + } + + // Reset logical size if needed + if (m_windowWidth != m_logicalWidth) { + SDL_RenderSetLogicalSize(m_renderer, m_logicalWidth, m_logicalHeight); + } + } +} +#endif // defined(__AUI_USE_SDL__) diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmovie.h b/ctp2_code/ui/aui_sdl/aui_sdlmovie.h new file mode 100644 index 000000000..5f2d0ca97 --- /dev/null +++ b/ctp2_code/ui/aui_sdl/aui_sdlmovie.h @@ -0,0 +1,61 @@ +#ifdef HAVE_PRAGMA_ONCE +#pragma once +#endif + +#ifndef __aui_sdl__aui_sdlmovie_h__ +#define __aui_sdl__aui_sdlmovie_h__ 1 + +#include "ctp2_config.h" +#include "aui_movie.h" + +#if defined(__AUI_USE_SDL__) + +#include + +class VideoState; +class SDL_Renderer; +class SDL_Texture; +class SDL_Surface; +class aui_SDLMovie : public aui_Movie { +public: + aui_SDLMovie(AUI_ERRCODE *retval, const MBCHAR * filename = NULL); + virtual ~aui_SDLMovie(); + + void SetContext(SDL_Renderer *renderer, SDL_Texture *background, const int windowWidth, const int windowHeight); + + virtual AUI_ERRCODE Load(); + virtual AUI_ERRCODE Unload(); + + virtual AUI_ERRCODE Open(uint32 flags = 0, aui_Surface *surface = NULL, RECT *rect = NULL); + virtual AUI_ERRCODE Close(); + + virtual AUI_ERRCODE Play(); + virtual AUI_ERRCODE Stop(); + + virtual AUI_ERRCODE Pause(); + virtual AUI_ERRCODE Resume(); + + virtual AUI_ERRCODE Process(); + + virtual BOOL IsOpen() const; + virtual BOOL IsPlaying() const; + virtual BOOL IsPaused() const; + +private: + bool HandleMovieEvent(SDL_Event &event); + bool InsideMovieArea(int x, int y); + void GrabLastFrame(); + + VideoState *m_videoState; + + SDL_Renderer *m_renderer; + SDL_Texture *m_background; + int m_windowWidth; + int m_windowHeight; + int m_logicalWidth; + int m_logicalHeight; +}; + +#endif // defined(__AUI_USE_SDL__) + +#endif diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp new file mode 100644 index 000000000..ef0d041d1 --- /dev/null +++ b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.cpp @@ -0,0 +1,69 @@ +#include "c3.h" +#include "aui_sdlmoviemanager.h" + +#if defined(__AUI_USE_SDL__) + +#include "aui_sdlmovie.h" + +#if defined(USE_SDL_FFMPEG) +#include +extern "C" { + #include +} + +static int lockmgr(void **mtx, enum AVLockOp op) +{ + switch(op) { + case AV_LOCK_CREATE: + *mtx = SDL_CreateMutex(); + if(!*mtx) { + av_log(NULL, AV_LOG_FATAL, "SDL_CreateMutex(): %s\n", SDL_GetError()); + return 1; + } + return 0; + case AV_LOCK_OBTAIN: + return !!SDL_LockMutex((SDL_mutex*) *mtx); + case AV_LOCK_RELEASE: + return !!SDL_UnlockMutex((SDL_mutex*) *mtx); + case AV_LOCK_DESTROY: + SDL_DestroyMutex((SDL_mutex*) *mtx); + return 0; + } + return 1; +} +#endif // USE_SDL_FFMPEG + +aui_SDLMovieManager::aui_SDLMovieManager(SDL_Renderer *renderer, SDL_Texture *background, const int windowWidth, + const int windowHeight) : + aui_MovieManager(false), + m_renderer(renderer), + m_background(background), + m_windowWidth(windowWidth), + m_windowHeight(windowHeight) +{ + Assert(m_renderer); + Assert(m_background); + m_movieResource = new aui_Resource(); + +#if defined(USE_SDL_FFMPEG) + av_register_all(); + if (av_lockmgr_register(lockmgr)) { + av_log(NULL, AV_LOG_FATAL, "Could not initialize lock manager!\n"); + } +#endif // USE_SDL_FFMPEG +} + +aui_SDLMovieManager::~aui_SDLMovieManager() { + delete m_movieResource; +#if defined(USE_SDL_FFMPEG) + av_lockmgr_register(NULL); +#endif // USE_SDL_FFMPEG +} + +aui_Movie* aui_SDLMovieManager::Load(const MBCHAR *filename, C3DIR dir) { + aui_SDLMovie *movie = m_movieResource->Load(filename, dir); + movie->SetContext(m_renderer, m_background, m_windowWidth, m_windowHeight); + return movie; +} + +#endif // defined(__AUI_USE_SDL__) diff --git a/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h new file mode 100644 index 000000000..bd4cea65f --- /dev/null +++ b/ctp2_code/ui/aui_sdl/aui_sdlmoviemanager.h @@ -0,0 +1,45 @@ +#ifdef HAVE_PRAGMA_ONCE +#pragma once +#endif + +#ifndef __aui_sdl__aui_sdlmoviemanager_h__ +#define __aui_sdl__aui_sdlmoviemanager_h__ 1 + +#include "ctp2_config.h" +#include "aui_moviemanager.h" + +#if defined(__AUI_USE_SDL__) + +#include "aui_sdlmovie.h" +#include + +class aui_SDLMovieManager : public aui_MovieManager { +public: + aui_SDLMovieManager(SDL_Renderer *sdlRenderer, SDL_Texture *background, const int windowWidth, + const int windowHeight); + virtual ~aui_SDLMovieManager(); + + virtual aui_Movie *Load(const MBCHAR *filename, C3DIR dir = C3DIR_DIRECT); + + virtual AUI_ERRCODE Unload( aui_Movie *movie ) + { return m_movieResource->Unload((aui_SDLMovie*)movie); } + virtual AUI_ERRCODE Unload( const MBCHAR *movie ) + { return m_movieResource->Unload(movie); } + + virtual AUI_ERRCODE AddSearchPath(const MBCHAR *path) + { return m_movieResource->AddSearchPath(path); } + virtual AUI_ERRCODE RemoveSearchPath(const MBCHAR *path) + { return m_movieResource->RemoveSearchPath(path); } + +private: + aui_Resource *m_movieResource; + + SDL_Renderer *m_renderer; + SDL_Texture *m_background; + int m_windowWidth; + int m_windowHeight; +}; + +#endif // defined(__AUI_USE_SDL__) + +#endif diff --git a/ctp2_code/ui/aui_sdl/aui_sdlsurface.cpp b/ctp2_code/ui/aui_sdl/aui_sdlsurface.cpp index 6bf130d82..51954f120 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlsurface.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlsurface.cpp @@ -6,7 +6,7 @@ #include "aui_ui.h" #include "aui_uniqueid.h" #include "aui_sdlsurface.h" -#include +#include uint32 aui_SDLSurface::m_SDLSurfaceClassId = aui_UniqueId(); @@ -36,10 +36,9 @@ aui_SDLSurface::aui_SDLSurface( Assert( AUI_SUCCESS(*retval) ); if ( !AUI_SUCCESS(*retval) ) return; - SDL_PixelFormat* fmt = SDL_GetVideoSurface()->format; if ( !(m_lpdds = lpdds) ) { - m_lpdds = (isPrimary)?SDL_GetVideoSurface():SDL_CreateRGBSurface(0, width, height, fmt->BitsPerPixel, fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask); + m_lpdds = CreateSDLSurface(width, height, bpp); if ( m_lpdds == NULL ) { *retval = AUI_ERRCODE_MEMALLOCFAILED; @@ -48,26 +47,14 @@ aui_SDLSurface::aui_SDLSurface( m_allocated = TRUE; // clear it with black if (SDL_FillRect(m_lpdds, NULL, 0) < 0) { - fprintf(stderr, "aui_Surface: Failed to erase new surface: %s\n", - SDL_GetError()); + fprintf(stderr, "aui_Surface: Failed to erase new surface: %s\n", SDL_GetError()); } } - else - { + else { m_allocated = takeOwnership; - } - - //just checking (fmt->Gmask >> fmt->Gshift == 0x3F) should be enough - //but save is save... - if ((fmt->Rmask >> fmt->Rshift == 0x1F) && (fmt->Gmask >> fmt->Gshift == 0x3F) && (fmt->Bmask >> fmt->Bshift == 0x1F)) { - m_pixelFormat = AUI_SURFACE_PIXELFORMAT_565; - //fprintf(stderr, "%s L%d: AUI_SURFACE_PIXELFORMAT_565\n", __FILE__, __LINE__); - } - if ((fmt->Rmask >> fmt->Rshift == 0x1F) && (fmt->Gmask >> fmt->Gshift == 0x1F) && (fmt->Bmask >> fmt->Bshift == 0x1F)) { - m_pixelFormat = AUI_SURFACE_PIXELFORMAT_555; - //fprintf(stderr, "%s L%d: AUI_SURFACE_PIXELFORMAT_555\n", __FILE__, __LINE__); - } + } + m_buffer = (uint8*) m_lpdds->pixels; m_pitch = m_lpdds->pitch; m_size = m_pitch * m_height; @@ -94,9 +81,36 @@ aui_SDLSurface::~aui_SDLSurface() SDL_DestroyMutex(m_bltMutex); } +uint32 aui_SDLSurface::TransformSurfacePixelFormatToSDL(const AUI_SURFACE_PIXELFORMAT pixelFormat) { + switch (pixelFormat) { + case AUI_SURFACE_PIXELFORMAT_332: + return SDL_PIXELFORMAT_RGB332; + case AUI_SURFACE_PIXELFORMAT_565: + return SDL_PIXELFORMAT_RGB565; + case AUI_SURFACE_PIXELFORMAT_555: + return SDL_PIXELFORMAT_RGB555; + case AUI_SURFACE_PIXELFORMAT_888: + return SDL_PIXELFORMAT_RGB888; + default: + return SDL_PIXELFORMAT_UNKNOWN; + } +} + +SDL_Surface* aui_SDLSurface::CreateSDLSurface(const int width, const int height, const int bpp) +{ + const AUI_SURFACE_PIXELFORMAT pixelFormat = TransformBppToSurfacePixelFormat(bpp); + + int sdlBpp; + uint32 rmask; + uint32 gmask; + uint32 bmask; + uint32 amask; + SDL_PixelFormatEnumToMasks(TransformSurfacePixelFormatToSDL(pixelFormat), &sdlBpp, &rmask, &gmask, &bmask, &amask); + return SDL_CreateRGBSurface(0, width, height, sdlBpp, rmask, gmask, bmask, amask); +} uint32 aui_SDLSurface::SetChromaKey( uint32 color ) { - int hr = SDL_SetColorKey(m_lpdds, SDL_SRCCOLORKEY, /*SDL_MapRGB(m_lpdds->format, color>>16, (color>>8)&0xff, color&0xff)*/color); //|SDL_RLEACCEL ? + int hr = SDL_SetColorKey(m_lpdds, SDL_TRUE, /*SDL_MapRGB(m_lpdds->format, color>>16, (color>>8)&0xff, color&0xff)*/color); //|SDL_RLEACCEL ? //hr == 0 if succeded! //fprintf(stderr, "%s L%d: SDL_SRCCOLORKEY set to %#X\n", __FILE__, __LINE__, color); diff --git a/ctp2_code/ui/aui_sdl/aui_sdlsurface.h b/ctp2_code/ui/aui_sdl/aui_sdlsurface.h index 4a7b49d7d..0081c1ca3 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlsurface.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlsurface.h @@ -30,6 +30,8 @@ class aui_SDLSurface : public aui_Surface, public aui_SDL { AUI_ERRCODE InitCommon( void ); public: + static uint32 TransformSurfacePixelFormatToSDL(const AUI_SURFACE_PIXELFORMAT pixelFormat); + virtual BOOL IsThisA( uint32 classId ) { return ((classId == m_SDLSurfaceClassId) || aui_Surface::IsThisA( classId ) @@ -54,8 +56,12 @@ class aui_SDLSurface : public aui_Surface, public aui_SDL { SDL_mutex* m_bltMutex; + SDL_Surface* GetSDLSurface() { return m_lpdds; } protected: SDL_Surface* m_lpdds; + +private: + SDL_Surface* CreateSDLSurface(const int width, const int height, const int bpp); }; typedef aui_SDLSurface aui_NativeSurface; diff --git a/ctp2_code/ui/aui_sdl/aui_sdlui.cpp b/ctp2_code/ui/aui_sdl/aui_sdlui.cpp index f1ec1deee..9003ad2d8 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlui.cpp +++ b/ctp2_code/ui/aui_sdl/aui_sdlui.cpp @@ -38,6 +38,7 @@ #include "aui_joystick.h" #include "aui_sdlsurface.h" #include "aui_sdlmouse.h" +#include "aui_sdlmoviemanager.h" #include "aui_sdlui.h" @@ -53,7 +54,8 @@ extern sint32 g_ScreenWidth; extern sint32 g_ScreenHeight; extern DisplayDevice g_displayDevice; -extern BOOL g_SDL_flags; +extern uint32 g_SDL_flags; //See ctp2_code/ctp/civ3_main.cpp +extern sint32 g_is565Format; aui_SDLUI::aui_SDLUI ( @@ -68,7 +70,10 @@ aui_SDLUI::aui_SDLUI ) : aui_UI (), aui_SDL (), - m_X11Display (0) + m_X11Display (0), + m_SDLWindow (0), + m_SDLRenderer (0), + m_SDLTexture (0) { *retval = aui_Region::InitCommon( 0, 0, 0, width, height ); @@ -122,7 +127,6 @@ AUI_ERRCODE aui_SDLUI::DestroyNativeScreen(void) { delete m_primary; m_primary = NULL; - m_lpdds = NULL; } return AUI_ERRCODE_OK; @@ -135,30 +139,31 @@ AUI_ERRCODE aui_SDLUI::CreateNativeScreen( BOOL useExclusiveMode ) assert( AUI_SUCCESS(errcode) ); if ( !AUI_SUCCESS(errcode) ) return errcode; - m_lpdds = SDL_SetVideoMode(m_width, m_height, m_bpp, g_SDL_flags); // mod by lynx |SDL_FULLSCREEN); - if (!m_lpdds) { - c3errors_FatalDialog("aui_SDLUI", SDL_GetError()); + m_pixelFormat = aui_Surface::TransformBppToSurfacePixelFormat(m_bpp); + m_SDLWindow = SDL_CreateWindow("Call To Power 2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, + m_width, m_height, g_SDL_flags); + if (!m_SDLWindow) { + c3errors_FatalDialog("aui_SDLUI", "SDL window creation failed:\n%s\n", SDL_GetError()); } - - m_primary = new aui_SDLSurface( - &errcode, - m_width, - m_height, - m_bpp, - m_lpdds, - TRUE ); + m_SDLRenderer = SDL_CreateRenderer(m_SDLWindow, -1, 0); + if (!m_SDLRenderer) { + c3errors_FatalDialog("aui_SDLUI", "SDL renderer creation failed:\n%s\n", SDL_GetError()); + } + SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); + SDL_RenderSetLogicalSize(m_SDLRenderer, m_width, m_height); + m_SDLTexture = SDL_CreateTexture(m_SDLRenderer, aui_SDLSurface::TransformSurfacePixelFormatToSDL(m_pixelFormat), + SDL_TEXTUREACCESS_STREAMING, m_width, m_height); + if (!m_SDLTexture) { + c3errors_FatalDialog("aui_SDLUI", "SDL texture creation failed:\n%s\n", SDL_GetError()); + } + + m_primary = new aui_SDLSurface(&errcode, m_width, m_height, m_bpp, NULL, TRUE); Assert( AUI_NEWOK(m_primary,errcode) ); assert( AUI_NEWOK(m_primary,errcode) ); if ( !AUI_NEWOK(m_primary,errcode) ) return AUI_ERRCODE_MEMALLOCFAILED; if(!m_secondary) { - m_secondary = new aui_SDLSurface( - &errcode, - m_width, - m_height, - m_bpp, - NULL, - FALSE ); + m_secondary = new aui_SDLSurface(&errcode, m_width, m_height, m_bpp, NULL, FALSE); Assert( AUI_NEWOK(m_primary,errcode) ); assert( AUI_NEWOK(m_primary,errcode) ); if ( !AUI_NEWOK(m_primary,errcode) ) return AUI_ERRCODE_MEMALLOCFAILED; @@ -179,16 +184,24 @@ aui_SDLUI::getDisplay() aui_SDLUI::~aui_SDLUI( void ) { - if ( m_lpdds ) { - // m_lpdds is deleted by SDL_Quit() - m_lpdds = NULL; - } #ifdef HAVE_X11 if (m_X11Display) { XCloseDisplay(m_X11Display); m_X11Display = 0; } #endif + if (m_SDLTexture) { + SDL_DestroyTexture(m_SDLTexture); + m_SDLTexture = NULL; + } + if (m_SDLRenderer) { + SDL_DestroyRenderer(m_SDLRenderer); + m_SDLRenderer = NULL; + } + if (m_SDLWindow) { + SDL_DestroyWindow(m_SDLWindow); + m_SDLWindow = NULL; + } } AUI_ERRCODE aui_SDLUI::TearDownMouse(void) @@ -333,4 +346,24 @@ AUI_ERRCODE aui_SDLUI::AltTabIn( void ) return FlushDirtyList(); } +aui_MovieManager* aui_SDLUI::CreateMovieManager( void ) { + Assert(m_SDLWindow); + Assert(m_SDLRenderer); + Assert(m_SDLTexture); + int windowWidth; + int windowHeight; + SDL_GetWindowSize(m_SDLWindow, &windowWidth, &windowHeight); + return new aui_SDLMovieManager(m_SDLRenderer, m_SDLTexture, windowWidth, windowHeight); +} + +AUI_ERRCODE aui_SDLUI::SDLDrawScreen( void ) { + Assert(m_primary); + Assert(m_SDLTexture); + Assert(m_SDLRenderer); + SDL_UpdateTexture(m_SDLTexture, NULL, m_primary->Buffer(), m_primary->Pitch()); + SDL_RenderClear(m_SDLRenderer); + SDL_RenderCopy(m_SDLRenderer, m_SDLTexture, NULL, NULL); + SDL_RenderPresent(m_SDLRenderer); +} + #endif // __AUI_USE_SDL__ diff --git a/ctp2_code/ui/aui_sdl/aui_sdlui.h b/ctp2_code/ui/aui_sdl/aui_sdlui.h index 210c17dbc..a465d7531 100644 --- a/ctp2_code/ui/aui_sdl/aui_sdlui.h +++ b/ctp2_code/ui/aui_sdl/aui_sdlui.h @@ -76,11 +76,16 @@ class aui_SDLUI : public aui_UI, public aui_SDL Display *getDisplay(); #endif + aui_MovieManager* CreateMovieManager( void ); protected: + virtual AUI_ERRCODE SDLDrawScreen( void ); + #if defined(HAVE_X11) Display * m_X11Display; #endif - SDL_Surface *m_lpdds; + SDL_Window *m_SDLWindow; + SDL_Renderer *m_SDLRenderer; + SDL_Texture *m_SDLTexture; }; typedef aui_SDLUI aui_NativeUI; diff --git a/ctp2_code/ui/interface/IntroMovieWin.cpp b/ctp2_code/ui/interface/IntroMovieWin.cpp index 08963aebd..0adf5c0f5 100644 --- a/ctp2_code/ui/interface/IntroMovieWin.cpp +++ b/ctp2_code/ui/interface/IntroMovieWin.cpp @@ -24,7 +24,7 @@ // // Modifications from the original Activision code: // -// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) +// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) // //---------------------------------------------------------------------------- diff --git a/ctp2_code/ui/interface/IntroMovieWindow.cpp b/ctp2_code/ui/interface/IntroMovieWindow.cpp index f91a2361f..116fa752a 100644 --- a/ctp2_code/ui/interface/IntroMovieWindow.cpp +++ b/ctp2_code/ui/interface/IntroMovieWindow.cpp @@ -24,7 +24,7 @@ // // Modifications from the original Activision code: // -// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) +// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) // //---------------------------------------------------------------------------- diff --git a/ctp2_code/ui/interface/chatbox.cpp b/ctp2_code/ui/interface/chatbox.cpp index a9d3255d6..04fecfaf2 100644 --- a/ctp2_code/ui/interface/chatbox.cpp +++ b/ctp2_code/ui/interface/chatbox.cpp @@ -73,7 +73,7 @@ #if defined(__AUI_USE_SDL__) -#include "SDL.h" +#include "SDL2/SDL.h" #include "civ3_main.h" #endif diff --git a/ctp2_code/ui/interface/controlpanelwindow.cpp b/ctp2_code/ui/interface/controlpanelwindow.cpp index 1e0392cc9..9dfb4fac0 100644 --- a/ctp2_code/ui/interface/controlpanelwindow.cpp +++ b/ctp2_code/ui/interface/controlpanelwindow.cpp @@ -32,22 +32,22 @@ // play. // - Start the great library with the current research project of the player. // - Added option to add new messages at the top. -// - Fixed crossed Sword bug. - Oct. 14th 2004 Martin Gühmann +// - Fixed crossed Sword bug. - Oct. 14th 2004 Martin Gühmann // - Fixed the crossed sword bug that was caused by the previous bug fix, -// cossed swords even if the city is hidden. - Oct. 15th 2004 Martin Gühmann +// cossed swords even if the city is hidden. - Oct. 15th 2004 Martin Gühmann // - Added unit display name. // - Relaxed Assert for invisible buttons with mods. // - Prevented crashes with mods. -// - Added special attack window. (Aug 15th 2005 Martin Gühmann) +// - Added special attack window. (Aug 15th 2005 Martin Gühmann) // - Removed unused methods: FillBank, ClearButtons and AddButton. -// (Aug 16th 2005 Martin Gühmann) +// (Aug 16th 2005 Martin Gühmann) // - Restored Fifth Tileimp Button Bank by E 2-27-2007 // - TODO fix obsolete tileimp defect // - TODO add buttons for orders button bank // - TODO create scroll bar like CityStyles in Scenario Editor for // Orders and tileimprovements so they are not limited -// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) -// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) +// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) +// - Replaced old const database by new one. (5-Aug-2007 Martin Gühmann) // //---------------------------------------------------------------------------- // @@ -58,8 +58,8 @@ // CityPanelRebuild - notice the strange immediate return) are never called, // and some variables (e.g. m_mainDropDown) are not NULL-initialised in the // constructor. Maybe this is some leftover of the CTP1 code? -// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) -// - Standatized code (May 21st 2006 Martin Gühmann) +// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) +// - Standatized code (May 21st 2006 Martin Gühmann) // - None of the unit or order stuff is used here? see UnitControlPanel.cpp // //---------------------------------------------------------------------------- @@ -2952,7 +2952,9 @@ void ControlPanelWindow::Idle() if (m_targetingMode) TargetingMode(); else - g_cursorManager->SetCursor(CURSORINDEX_DEFAULT); + // prevent resetting of scroll-cursor + if (!g_tiledMap->IsScrolling()) + g_cursorManager->SetCursor(CURSORINDEX_DEFAULT); } void ControlPanelWindow::Move( sint32 x, sint32 y ) diff --git a/ctp2_code/ui/interface/initialplayscreen.cpp b/ctp2_code/ui/interface/initialplayscreen.cpp index 8a805cc68..62ea07ff4 100644 --- a/ctp2_code/ui/interface/initialplayscreen.cpp +++ b/ctp2_code/ui/interface/initialplayscreen.cpp @@ -304,7 +304,12 @@ void initialplayscreen_tutorialPress(aui_Control *control, uint32 action, uint32 { if ( action != (uint32)AUI_BUTTON_ACTION_EXECUTE ) return; - if (c3files_HasLegalCD()) { +#if defined(USE_SDL) + bool legalGame = true; +#else // USE_SDL + bool legalGame = c3files_HasLegalCD(); +#endif // USE_SDL + if (legalGame) { if(initialplayscreen_removeMyWindow(action)) { g_theProfileDB->SetTutorialAdvice(TRUE); g_civApp->PostStartGameAction(); diff --git a/ctp2_code/ui/interface/loadsavescreen.cpp b/ctp2_code/ui/interface/loadsavescreen.cpp index 8d4799a65..407263d31 100644 --- a/ctp2_code/ui/interface/loadsavescreen.cpp +++ b/ctp2_code/ui/interface/loadsavescreen.cpp @@ -26,15 +26,15 @@ // // - Repaired memory leaks. // - Updated tribe index check. -// - Replaced the old civilisation database by a new one. (Aug 21st 2005 Martin Gühmann) -// - Standardized code (May 21st 2006 Martin Gühmann) +// - Replaced the old civilisation database by a new one. (Aug 21st 2005 Martin G�hmann) +// - Standardized code (May 21st 2006 Martin G�hmann) // //---------------------------------------------------------------------------- // // Remarks // // - This is the only file with some Activision comments left. -// - Fixed scenarios so that the from the civ choser selected civ is used. (2-Jan-2008 Martin Gühmann) +// - Fixed scenarios so that the from the civ choser selected civ is used. (2-Jan-2008 Martin G�hmann) // //---------------------------------------------------------------------------- @@ -642,7 +642,10 @@ void loadsavescreen_LoadGame(void) Assert(gameInfo); if (!gameInfo) return; + +#if !defined(USE_SDL) if (!c3files_HasLegalCD()) return; +#endif // USE_SDL if (SaveInfo * saveInfo = g_loadsaveWindow->GetSaveInfo()) { @@ -797,7 +800,12 @@ void loadsavescreen_LoadMPGame(void) } // SAM042099 check for a valid CD-ROM before allowing a game to be loaded - if ((!g_netfunc || g_netfunc->IsHost()) && !c3files_HasLegalCD()) +#if defined(USE_SDL) + bool legalGame = true; +#else // USE_SDL + bool legalGame = c3files_HasLegalCD(); +#endif // USE_SDL + if ((!g_netfunc || g_netfunc->IsHost()) && !legalGame) return; GameInfo * gameInfo = g_loadsaveWindow->GetGameInfo(); @@ -896,8 +904,10 @@ void loadsavescreen_SaveMPGame(void) void loadsavescreen_LoadSCENGame(void) { +#if !defined(USE_SDL) // SAM042099 check for a valid CD-ROM before allowing a game to be loaded if (!c3files_HasLegalCD()) return; +#endif // USE_SDL GameInfo *gameInfo = g_loadsaveWindow->GetGameInfo(); diff --git a/ctp2_code/ui/interface/spnewgamescreen.cpp b/ctp2_code/ui/interface/spnewgamescreen.cpp index 9015eed43..0937857dc 100644 --- a/ctp2_code/ui/interface/spnewgamescreen.cpp +++ b/ctp2_code/ui/interface/spnewgamescreen.cpp @@ -252,7 +252,12 @@ spnewgamescreen_startPress(aui_Control *control, uint32 action, uint32 data, voi { if ( action == uint32(AUI_BUTTON_ACTION_EXECUTE) ) { - if (c3files_HasLegalCD()) +#if defined(USE_SDL) + bool legalGame = true; +#else // USE_SDL + bool legalGame = c3files_HasLegalCD(); +#endif // USE_SDL + if (legalGame) { MBCHAR fieldText[k_MAX_NAME_LEN]; g_spNewGameWindow->m_spName->GetFieldText(fieldText, k_MAX_NAME_LEN); @@ -397,8 +402,11 @@ void spnewgamescreen_scenarioExitCallback(aui_Control *control, uint32 action, u ); if (c3files_PathIsValid(tempPath)) { + +#if !defined(USE_SDL) if(!c3files_HasLegalCD()) exit(0); +#endif // USE_SDL SaveInfo *saveInfo = new SaveInfo; diff --git a/ctp2_code/ui/netshell/allinonewindow.cpp b/ctp2_code/ui/netshell/allinonewindow.cpp index 34aa01d5e..49a3e06e5 100644 --- a/ctp2_code/ui/netshell/allinonewindow.cpp +++ b/ctp2_code/ui/netshell/allinonewindow.cpp @@ -28,11 +28,11 @@ // Modifications from the original Activision code: // // - Memory leak repaired. -// - Replaced old civilisation database by new one. (Aug 21st 2005 Martin Gühmann) +// - Replaced old civilisation database by new one. (Aug 21st 2005 Martin G�hmann) // - The ages in the summary are now displayed correctly. -// - Initialized local variables. (Sep 9th 2005 Martin Gühmann) -// - Standardized code. (May 29th 2006 Martin Gühmann) -// - Replaced old civ selection button bank by list box. (2-Jan-2008 Martin Gühmann) +// - Initialized local variables. (Sep 9th 2005 Martin G�hmann) +// - Standardized code. (May 29th 2006 Martin G�hmann) +// - Replaced old civ selection button bank by list box. (2-Jan-2008 Martin G�hmann) // //---------------------------------------------------------------------------- @@ -3585,7 +3585,12 @@ void AllinoneWindow::OKButtonAction::Execute( if ( g_playersetup.IsReadyToLaunch() ) return; - if (g_netfunc->IsHost() && !c3files_HasLegalCD() ) +#if defined(USE_SDL) + bool legalGame = true; +#else // USE_SDL + bool legalGame = c3files_HasLegalCD(); +#endif // USE_SDL + if (g_netfunc->IsHost() && !legalGame ) { static ns_String donthavecd( "strings.system.donthavecd" ); g_netfunc->PushChatMessage( donthavecd.GetString() ); diff --git a/ctp2_code/ui/netshell/netfunc.cpp b/ctp2_code/ui/netshell/netfunc.cpp index 1878a0349..e88e27839 100644 --- a/ctp2_code/ui/netshell/netfunc.cpp +++ b/ctp2_code/ui/netshell/netfunc.cpp @@ -47,8 +47,8 @@ #endif #ifdef USE_SDL -#include -#include +#include +#include #endif #ifdef WIN32 @@ -2460,7 +2460,7 @@ NETFunc::STATUS NETFunc::SetTransport(Transport *t) { } cancelDial = 0; #ifdef USE_SDL - threadHandle = SDL_CreateThread(ConnectThread, (void *)transport); + threadHandle = SDL_CreateThread(ConnectThread, "Connect-thread", (void *)transport); #else threadHandle = CreateThread(0, 0, ConnectThread, (void *)transport, 0, &threadId); #endif @@ -2903,7 +2903,7 @@ NETFunc::STATUS NETFunc::Connect(dp_t *d, PlayerStats *stats, bool h) { return ERR; #ifdef USE_SDL - threadHandle = SDL_CreateThread(ReConnectThread, (void *) &reconnected); + threadHandle = SDL_CreateThread(ReConnectThread, "Reconnect-thread", (void *) &reconnected); #else threadHandle = CreateThread(0, 0, ReConnectThread, (void *)&reconnected, 0, &threadId); #endif diff --git a/ctp2_code/ui/netshell/netfunc.h b/ctp2_code/ui/netshell/netfunc.h index d8bbac8d6..bded23b50 100644 --- a/ctp2_code/ui/netshell/netfunc.h +++ b/ctp2_code/ui/netshell/netfunc.h @@ -51,8 +51,8 @@ #include #ifdef USE_SDL -#include -#include +#include +#include #endif #if defined(WIN32) diff --git a/ctp2_data/default/uidata/layouts/wondermovie.ldl b/ctp2_data/default/uidata/layouts/wondermovie.ldl index 28f1fe1e5..923fca7c9 100644 --- a/ctp2_data/default/uidata/layouts/wondermovie.ldl +++ b/ctp2_data/default/uidata/layouts/wondermovie.ldl @@ -9,7 +9,7 @@ WonderMovieWindow { string xanchor "center" string yanchor "center" int widthpix 338 - int heightpix 357 + int heightpix 360 string pattern "uptg20e.tga" MovieButton { @@ -39,7 +39,7 @@ WonderMovieWindow { int xpix 0 int ypix 48 int widthpix 9 - int heightpix 292 + int heightpix 295 string pattern "upba6701.tga" } @@ -47,13 +47,13 @@ WonderMovieWindow { int xpix 329 int ypix 48 int widthpix 9 - int heightpix 292 + int heightpix 295 string pattern "upba6702.tga" } BottomBorder { int xpix 0 - int ypix 340 + int ypix 343 int widthpix 338 int heightpix 17