diff --git a/sc2/src/libs/graphics/sdl/dcqueue.c b/sc2/src/libs/graphics/sdl/dcqueue.c index 40da71b0a..bb7b79348 100644 --- a/sc2/src/libs/graphics/sdl/dcqueue.c +++ b/sc2/src/libs/graphics/sdl/dcqueue.c @@ -206,6 +206,14 @@ TFB_DrawCommandQueue_Clear () UnlockRecursiveMutex (DCQ_Mutex); } +static inline int +rects_equal (RECT *r1, RECT *r2) +{ + return r1->corner.x == r2->corner.x && r1->corner.y == r2->corner.y + && r1->extent.width == r2->extent.width + && r1->extent.height == r2->extent.height; +} + void TFB_EnqueueDrawCommand (TFB_DrawCommand* DrawCommand) { @@ -220,17 +228,17 @@ TFB_EnqueueDrawCommand (TFB_DrawCommand* DrawCommand) static RECT scissor_rect; // Set the clipping region. - if (scissor_rect.corner.x != _pCurContext->ClipRect.corner.x - || scissor_rect.corner.y != _pCurContext->ClipRect.corner.y - || scissor_rect.extent.width != - _pCurContext->ClipRect.extent.width - || scissor_rect.extent.height != - _pCurContext->ClipRect.extent.height) + // We allow drawing with no current context set, so the whole screen + if ((_pCurContext && !rects_equal (&scissor_rect, &_pCurContext->ClipRect)) + || (!_pCurContext && scissor_rect.extent.width != 0)) { // Enqueue command to set the glScissor spec TFB_DrawCommand DC; - scissor_rect = _pCurContext->ClipRect; + if (_pCurContext) + scissor_rect = _pCurContext->ClipRect; + else + scissor_rect.extent.width = 0; if (scissor_rect.extent.width) { diff --git a/sc2/src/libs/video/legacyplayer.c b/sc2/src/libs/video/legacyplayer.c index 80f099cdc..2e4986ef5 100644 --- a/sc2/src/libs/video/legacyplayer.c +++ b/sc2/src/libs/video/legacyplayer.c @@ -1,39 +1,82 @@ -#include "vidintrn.h" +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ -BOOLEAN +#include "vidintrn.h" +#include "video.h" +#include "vidplayer.h" +#include "libs/memlib.h" + + +LEGACY_VIDEO_REF PlayLegacyVideo (LEGACY_VIDEO vid) { const char *name, *audname, *speechname; - DWORD loopframe; - VIDEO_REF VidRef; - MUSIC_REF AudRef = 0; - MUSIC_REF SpeechRef = 0; + uint32 loopframe; + LEGACY_VIDEO_REF ref; + VIDEO_TYPE type; if (!vid) - return FALSE; + return NULL; + ref = HCalloc (sizeof (*ref)); + if (!ref) + return NULL; name = vid->video; audname = vid->audio; speechname = vid->speech; loopframe = vid->loop; - VidRef = LoadVideoFile (name); - if (!VidRef) - return FALSE; + ref->vidref = LoadVideoFile (name); + if (!ref->vidref) + return NULL; if (audname) - AudRef = LoadMusicFile (audname); + ref->audref = LoadMusicFile (audname); if (speechname) - SpeechRef = LoadMusicFile (speechname); + ref->speechref = LoadMusicFile (speechname); - VidPlayEx (VidRef, AudRef, SpeechRef, loopframe); - VidDoInput (); - VidStop (); + type = VidPlayEx (ref->vidref, ref->audref, ref->speechref, loopframe); + if (type == NO_FMV) + { // Video failed to start + StopLegacyVideo (ref); + return NULL; + } - DestroyVideo (VidRef); - if (SpeechRef) - DestroyMusic (SpeechRef); - if (AudRef) - DestroyMusic (AudRef); - - return TRUE; + return ref; } +void +StopLegacyVideo (LEGACY_VIDEO_REF ref) +{ + if (!ref) + return; + if (TFB_VideoPlaying (ref->vidref)) + VidStop (); + + DestroyVideo (ref->vidref); + if (ref->speechref) + DestroyMusic (ref->speechref); + if (ref->audref) + DestroyMusic (ref->audref); + + HFree (ref); +} + +BOOLEAN +PlayingLegacyVideo (LEGACY_VIDEO_REF ref) +{ + if (!ref) + return FALSE; + return TFB_VideoPlaying (ref->vidref); +} diff --git a/sc2/src/libs/video/video.c b/sc2/src/libs/video/video.c index 1cd41a255..a6f860275 100644 --- a/sc2/src/libs/video/video.c +++ b/sc2/src/libs/video/video.c @@ -16,12 +16,11 @@ #include "video.h" +#include "vidintrn.h" #include "options.h" #include "vidplayer.h" -#include "libs/inplib.h" #include "libs/memlib.h" -// XXX: we should not include anything from uqm/ inside libs/ -#include "uqm/setup.h" +#include "libs/sndlib.h" #define NULL_VIDEO_REF (0) @@ -52,21 +51,18 @@ UninitVideoPlayer (void) } void -VidStop () +VidStop (void) { if (_cur_speech) snd_StopSpeech (); if (_cur_video) - { TFB_StopVideo (_cur_video); - TFB_FadeClearScreen (); - } _cur_speech = 0; _cur_video = NULL_VIDEO_REF; } VIDEO_REF -VidPlaying () +VidPlaying (void) // this should just probably return BOOLEAN { if (!_cur_video) @@ -78,6 +74,24 @@ VidPlaying () return NULL_VIDEO_REF; } +// return current video position in milliseconds +DWORD +VidGetPosition (void) +{ + if (!VidPlaying ()) + return 0; + return TFB_GetVideoPosition (_cur_video); +} + +BOOLEAN +VidSeek (DWORD pos) + // pos in milliseconds +{ + if (!VidPlaying ()) + return FALSE; + return TFB_SeekVideo (_cur_video, pos); +} + VIDEO_TYPE VidPlayEx (VIDEO_REF vid, MUSIC_REF AudRef, MUSIC_REF SpeechRef, DWORD LoopFrame) @@ -105,13 +119,10 @@ VidPlayEx (VIDEO_REF vid, MUSIC_REF AudRef, MUSIC_REF SpeechRef, _cur_speech = 0; _cur_video = NULL_VIDEO_REF; - TFB_FadeClearScreen (); - FlushInput (); LockMutex (GraphicsLock); - SetContext (ScreenContext); // play video in the center of the screen - if (TFB_PlayVideo (vid, (SCREEN_WIDTH - vid->w) / 2, - (SCREEN_HEIGHT - vid->h) / 2)) + if (TFB_PlayVideo (vid, (ScreenWidth - vid->w) / 2, + (ScreenHeight - vid->h) / 2)) { _cur_video = vid; ret = SOFTWARE_FMV; @@ -136,13 +147,6 @@ VidPlay (VIDEO_REF VidRef) return VidPlayEx (VidRef, 0, 0, VID_NO_LOOP); } -void -VidDoInput (void) -{ - if (_cur_video) - TFB_VideoInput (_cur_video); -} - VIDEO_REF _init_video_file (const char *pStr) { @@ -153,7 +157,7 @@ _init_video_file (const char *pStr) if (!dec) return NULL_VIDEO_REF; - vid = (TFB_VideoClip*) HCalloc (sizeof (*vid)); + vid = HCalloc (sizeof (*vid)); vid->decoder = dec; vid->length = dec->length; vid->w = vid->decoder->w; diff --git a/sc2/src/libs/video/video.h b/sc2/src/libs/video/video.h index 047eefbb9..bd652d697 100644 --- a/sc2/src/libs/video/video.h +++ b/sc2/src/libs/video/video.h @@ -18,6 +18,7 @@ #define _UQM_VIDEO_H #include "libs/vidlib.h" +#include "libs/sndlib.h" #include "libs/graphics/tfb_draw.h" #include "types.h" #include "videodec.h" diff --git a/sc2/src/libs/video/videodec.c b/sc2/src/libs/video/videodec.c index 26016cc47..b99a442f8 100644 --- a/sc2/src/libs/video/videodec.c +++ b/sc2/src/libs/video/videodec.c @@ -245,7 +245,7 @@ VideoDecoder_Load (uio_DirHandle *dir, const char *filename) return NULL; } - decoder = (TFB_VideoDecoder*) HCalloc (info->funcs->GetStructSize ()); + decoder = HCalloc (info->funcs->GetStructSize ()); decoder->funcs = info->funcs; if (!decoder->funcs->Init (decoder, &vd_vidfmt)) { diff --git a/sc2/src/libs/video/vidintrn.h b/sc2/src/libs/video/vidintrn.h index 047f21bd0..2d5819017 100644 --- a/sc2/src/libs/video/vidintrn.h +++ b/sc2/src/libs/video/vidintrn.h @@ -19,11 +19,29 @@ #ifndef VIDINTERN_H_ #define VIDINTERN_H_ +#include "types.h" #include "libs/vidlib.h" +#include "libs/threadlib.h" -typedef struct legacy_video_desc { +struct legacy_video_desc +{ char *video, *audio, *speech; - DWORD loop; -} LEGACY_VIDEO_DESC; + uint32 loop; +}; + +typedef struct legacy_video_desc LEGACY_VIDEO_DESC; + +struct legacy_video_ref +{ + VIDEO_REF vidref; + MUSIC_REF audref; + MUSIC_REF speechref; +}; + +// XXX: There has to be a better way to synchronize gfx calls with the rest +// of the game. The only thing we need to sync is the current context, and +// even there only the cliprect. Perhaps a DCQ command that takes an +// explicit cliprect would be better. +extern Mutex GraphicsLock; #endif diff --git a/sc2/src/libs/video/vidplayer.c b/sc2/src/libs/video/vidplayer.c index 220604def..1ddc6dc05 100644 --- a/sc2/src/libs/video/vidplayer.c +++ b/sc2/src/libs/video/vidplayer.c @@ -16,15 +16,12 @@ #include "vidplayer.h" +#include "vidintrn.h" #include "libs/graphics/gfx_common.h" #include "libs/graphics/tfb_draw.h" #include "libs/log.h" #include "libs/memlib.h" -// XXX: we should not include anything from uqm/ inside libs/ -#include "uqm/controls.h" -#include "uqm/settings.h" -#include "uqm/setup.h" -#include "uqm/sounds.h" +#include "libs/sndlib.h" // video callbacks static void vp_BeginFrame (TFB_VideoDecoder*); @@ -62,16 +59,6 @@ static TFB_SoundCallbacks vp_AudioCBs = static Semaphore vp_interthread_lock = 0; static void* vp_interthread_clip = NULL; -typedef struct -{ - // standard state required by DoInput - BOOLEAN (*InputFunc) (void *pInputState); - COUNT MenuRepeatDelay; - - VIDEO_REF CurVideo; - -} VIDEO_INPUT_STATE; - bool TFB_InitVideoPlayer (void) { @@ -87,29 +74,6 @@ TFB_UninitVideoPlayer (void) DestroySemaphore (vp_interthread_lock); } -void -TFB_FadeClearScreen (void) -{ - BYTE xform_buf[1]; - RECT r = {{0, 0}, {SCREEN_WIDTH, SCREEN_HEIGHT}}; - - xform_buf[0] = FadeAllToBlack; - SleepThreadUntil (XFormColorMap ( - (COLORMAPPTR) xform_buf, ONE_SECOND / 2)); - - // paint black rect over screen - LockMutex (GraphicsLock); - SetContext (ScreenContext); - SetContextForeGroundColor ( - BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)); - DrawFilledRectangle (&r); - UnlockMutex (GraphicsLock); - - // fade in black rect instantly - xform_buf[0] = FadeAllToColor; - XFormColorMap ((COLORMAPPTR) xform_buf, 0); -} - // audio-synced video playback task // the frame rate and timing is dictated by the audio static int @@ -131,7 +95,7 @@ as_video_play_task (void *data) LockMutex (vid->guard); want_frame = vid->want_frame; if (vid->hAudio) - PlayMusic (vid->hAudio, FALSE, 1); + PLRPlaySong (vid->hAudio, FALSE, 1); UnlockMutex (vid->guard); clagged = 0; @@ -201,11 +165,15 @@ as_video_play_task (void *data) // draw the frame if (ret > 0) { + CONTEXT oldContext; + LockMutex (GraphicsLock); - SetContext (ScreenContext); + // We have the cliprect precalculated and don't need the rest + oldContext = SetContext (NULL); TFB_DrawScreen_Image (vid->frame, vid->dst_rect.corner.x, vid->dst_rect.corner.y, GSCALE_IDENTITY, NULL, TFB_SCREEN_MAIN); + SetContext (oldContext); UnlockMutex (GraphicsLock); FlushGraphics (); // needed to prevent half-frame updates } @@ -217,7 +185,7 @@ as_video_play_task (void *data) ret = VideoDecoder_Decode (vid->decoder); } if (vid->hAudio) - StopMusic (); + PLRStop (vid->hAudio); vid->playing = false; FinishTask (task); @@ -241,7 +209,7 @@ video_play_task (void *data) LockMutex (vid->guard); if (vid->hAudio) - PlayMusic (vid->hAudio, (vid->loop_frame != VID_NO_LOOP), 1); + PLRPlaySong (vid->hAudio, (vid->loop_frame != VID_NO_LOOP), 1); UnlockMutex (vid->guard); @@ -258,15 +226,19 @@ video_play_task (void *data) while (!Task_ReadState (task, TASK_EXIT) && ret > 0) { + CONTEXT oldContext; + // wait till its time to render next frame SleepThreadUntil (vid->frame_time); vid->cur_frame = vid->decoder->cur_frame; LockMutex (GraphicsLock); - SetContext (ScreenContext); + // We have the cliprect precalculated and don't need the rest + oldContext = SetContext (NULL); TFB_DrawScreen_Image (vid->frame, vid->dst_rect.corner.x, vid->dst_rect.corner.y, GSCALE_IDENTITY, NULL, TFB_SCREEN_MAIN); + SetContext (oldContext); UnlockMutex (GraphicsLock); FlushGraphics (); // needed to prevent half-frame updates @@ -277,7 +249,7 @@ video_play_task (void *data) } vid->playing = false; if (vid->hAudio) - StopMusic (); + PLRStop (vid->hAudio); FinishTask (task); @@ -289,7 +261,7 @@ TFB_PlayVideo (VIDEO_REF vid, uint32 x, uint32 y) { RECT scrn_r; RECT clip_r = {{0, 0}, {vid->w, vid->h}}; - RECT vid_r = {{0, 0}, {SCREEN_WIDTH, SCREEN_HEIGHT}}; + RECT vid_r = {{0, 0}, {ScreenWidth, ScreenHeight}}; RECT dr = {{x, y}, {vid->w, vid->h}}; RECT sr; @@ -333,8 +305,6 @@ TFB_PlayVideo (VIDEO_REF vid, uint32 x, uint32 y) vid->own_audio = true; } - StopMusic (); - if (vid->decoder->audio_synced) { TFB_SoundSample **pmus; @@ -389,7 +359,7 @@ TFB_StopVideo (VIDEO_REF vid) if (vid->hAudio) { - StopMusic (); + PLRStop (vid->hAudio); if (vid->own_audio) { DestroyMusic (vid->hAudio); @@ -413,67 +383,42 @@ TFB_VideoPlaying (VIDEO_REF vid) return vid->playing; } -static BOOLEAN -TFB_DoVideoInput (void *pIS) +uint32 +TFB_GetVideoPosition (VIDEO_REF vid) { - VIDEO_INPUT_STATE* pVIS = (VIDEO_INPUT_STATE*) pIS; - TFB_VideoClip* vid = pVIS->CurVideo; + uint32 pos; - if (!pVIS->CurVideo || !TFB_VideoPlaying (pVIS->CurVideo)) - return FALSE; + if (!TFB_VideoPlaying (vid)) + return 0; - if (PulsedInputState.menu[KEY_MENU_SELECT] - || PulsedInputState.menu[KEY_MENU_CANCEL] - || PulsedInputState.menu[KEY_MENU_SPECIAL] - || (GLOBAL (CurrentActivity) & CHECK_ABORT)) - { // abort movie - TFB_StopVideo (pVIS->CurVideo); - return FALSE; - } - else if (PulsedInputState.menu[KEY_MENU_LEFT] || PulsedInputState.menu[KEY_MENU_RIGHT]) - { - if (vid->decoder->audio_synced) - { - float newpos; - - LockMutex (vid->guard); - newpos = vid->decoder->pos; - UnlockMutex (vid->guard); + LockMutex (vid->guard); + pos = (uint32) (vid->decoder->pos * 1000); + UnlockMutex (vid->guard); - if (PulsedInputState.menu[KEY_MENU_LEFT]) - newpos -= 2; - else if (PulsedInputState.menu[KEY_MENU_RIGHT]) - newpos += 1; - if (newpos < 0) - newpos = 0; - - LockMutex (soundSource[MUSIC_SOURCE].stream_mutex); - SeekStream (MUSIC_SOURCE, (uint32) (newpos * 1000)); - UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex); - - TaskSwitch (); - } - // non a/s decoder seeking is not supported yet - } - else - { - SleepThread (ONE_SECOND / 30); - } - - return TRUE; + return pos; } -void -TFB_VideoInput (VIDEO_REF VidRef) +bool +TFB_SeekVideo (VIDEO_REF vid, uint32 pos) { - VIDEO_INPUT_STATE vis; + if (!TFB_VideoPlaying (vid)) + return false; - vis.MenuRepeatDelay = 0; - vis.InputFunc = TFB_DoVideoInput; - vis.CurVideo = VidRef; - - SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); - DoInput (&vis, TRUE); + if (vid->decoder->audio_synced) + { + LockMutex (soundSource[MUSIC_SOURCE].stream_mutex); + SeekStream (MUSIC_SOURCE, pos); + UnlockMutex (soundSource[MUSIC_SOURCE].stream_mutex); + TaskSwitch (); + return true; + } + else + { // TODO: Non-a/s decoder seeking is not supported yet + // Decide what to do with these. Seeking this kind of + // video is trivial, but we may not want to do it. + // The only non-a/s videos right now are ship spins. + return false; + } } static void diff --git a/sc2/src/libs/video/vidplayer.h b/sc2/src/libs/video/vidplayer.h index 0ee555d81..6e9846fe9 100644 --- a/sc2/src/libs/video/vidplayer.h +++ b/sc2/src/libs/video/vidplayer.h @@ -19,13 +19,12 @@ #include "video.h" -bool TFB_InitVideoPlayer (void); -void TFB_UninitVideoPlayer (void); -void TFB_FadeClearScreen (void); -bool TFB_PlayVideo (VIDEO_REF VidRef, uint32 x, uint32 y); -void TFB_StopVideo (VIDEO_REF VidRef); -bool TFB_VideoPlaying (VIDEO_REF VidRef); -void TFB_VideoInput (VIDEO_REF VidRef); - +extern bool TFB_InitVideoPlayer (void); +extern void TFB_UninitVideoPlayer (void); +extern bool TFB_PlayVideo (VIDEO_REF VidRef, uint32 x, uint32 y); +extern void TFB_StopVideo (VIDEO_REF VidRef); +extern bool TFB_VideoPlaying (VIDEO_REF VidRef); +extern uint32 TFB_GetVideoPosition (VIDEO_REF VidRef); +extern bool TFB_SeekVideo (VIDEO_REF VidRef, uint32 pos); #endif // _VIDPLAYER_H diff --git a/sc2/src/libs/video/vresins.c b/sc2/src/libs/video/vresins.c index 58011315c..dbb18e061 100644 --- a/sc2/src/libs/video/vresins.c +++ b/sc2/src/libs/video/vresins.c @@ -47,7 +47,7 @@ GetLegacyVideoData (const char *path, RESOURCE_DATA *resdata) { void *result = NULL; char paths[1024], *audio_path, *speech_path, *loop_str; - DWORD LoopFrame = VID_NO_LOOP; + uint32 LoopFrame = VID_NO_LOOP; /* Parse out the video components. */ strncpy (paths, path, 1023); @@ -93,13 +93,13 @@ GetLegacyVideoData (const char *path, RESOURCE_DATA *resdata) if (loop_str) { char *end; - LoopFrame = (DWORD) strtol (loop_str, &end, 10); + LoopFrame = strtol (loop_str, &end, 10); // We allow whitespace at the end, but nothing printable. if (*end > 32) { log_add (log_Warning, "Warning: Unparsable loop frame '%s'. Disabling loop.", loop_str); LoopFrame = VID_NO_LOOP; } - log_add (log_Info, "\tLoop frame is %d", LoopFrame); + log_add (log_Info, "\tLoop frame is %u", LoopFrame); } else log_add (log_Info, "\tNo specified loop frame"); diff --git a/sc2/src/libs/vidlib.h b/sc2/src/libs/vidlib.h index d8d2d5b74..bdab2765e 100644 --- a/sc2/src/libs/vidlib.h +++ b/sc2/src/libs/vidlib.h @@ -32,6 +32,7 @@ typedef enum typedef struct tfb_videoclip *VIDEO_REF; typedef struct legacy_video_desc *LEGACY_VIDEO; +typedef struct legacy_video_ref *LEGACY_VIDEO_REF; extern BOOLEAN InstallVideoResType (void); @@ -39,17 +40,20 @@ extern BOOLEAN InitVideoPlayer (BOOLEAN UseCDROM); extern void UninitVideoPlayer (void); extern VIDEO_REF LoadVideoFile (const char *pStr); -extern BOOLEAN DestroyVideo (VIDEO_REF VideoRef); +extern BOOLEAN DestroyVideo (VIDEO_REF VidRef); extern VIDEO_TYPE VidPlay (VIDEO_REF VidRef); extern VIDEO_TYPE VidPlayEx (VIDEO_REF VidRef, MUSIC_REF AudRef, MUSIC_REF SpeechRef, DWORD LoopFrame); #define VID_NO_LOOP (0U-1) extern void VidStop (void); extern VIDEO_REF VidPlaying (void); -extern void VidDoInput (void); +extern DWORD VidGetPosition (void); // position in milliseconds +extern BOOLEAN VidSeek (DWORD pos); // position in milliseconds -LEGACY_VIDEO LoadLegacyVideoInstance (RESOURCE res); -BOOLEAN PlayLegacyVideo (LEGACY_VIDEO vid); -BOOLEAN DestroyLegacyVideo (LEGACY_VIDEO vid); +extern LEGACY_VIDEO LoadLegacyVideoInstance (RESOURCE res); +extern BOOLEAN DestroyLegacyVideo (LEGACY_VIDEO vid); +extern LEGACY_VIDEO_REF PlayLegacyVideo (LEGACY_VIDEO vid); +extern void StopLegacyVideo (LEGACY_VIDEO_REF ref); +extern BOOLEAN PlayingLegacyVideo (LEGACY_VIDEO_REF ref); #endif /* _VIDLIB_H */ diff --git a/sc2/src/uqm/intro.c b/sc2/src/uqm/intro.c index d5ae88de2..b6ff35f62 100644 --- a/sc2/src/uqm/intro.c +++ b/sc2/src/uqm/intro.c @@ -85,6 +85,16 @@ typedef struct { int debounce; } SPINANIM_INPUT_STATE; +typedef struct +{ + // standard state required by DoInput + BOOLEAN (*InputFunc) (void *pInputState); + COUNT MenuRepeatDelay; + + LEGACY_VIDEO_REF CurVideo; + +} VIDEO_INPUT_STATE; + static BOOLEAN DoPresentation (void *pIS); static BOOLEAN @@ -795,7 +805,6 @@ ShowSlidePresentation (STRING PresStr) DestroyDrawable (ReleaseDrawable (pis.Frame)); for (i = 0; i < MAX_FONTS; ++i) DestroyFont (pis.Fonts[i]); - DestroyStringTable (ReleaseStringTable (pis.SlideShow)); LockMutex (GraphicsLock); SetContextFont (OldFont); @@ -806,6 +815,96 @@ ShowSlidePresentation (STRING PresStr) return TRUE; } +static BOOLEAN +DoVideoInput (void *pIS) +{ + VIDEO_INPUT_STATE* pVIS = (VIDEO_INPUT_STATE*) pIS; + + if (!PlayingLegacyVideo (pVIS->CurVideo)) + { // Video probably finished + // Have to call VidStop anyway to cleanup + VidStop (); + return FALSE; + } + + if (PulsedInputState.menu[KEY_MENU_SELECT] + || PulsedInputState.menu[KEY_MENU_CANCEL] + || PulsedInputState.menu[KEY_MENU_SPECIAL] + || (GLOBAL (CurrentActivity) & CHECK_ABORT)) + { // abort movie + VidStop (); + return FALSE; + } + else if (PulsedInputState.menu[KEY_MENU_LEFT] + || PulsedInputState.menu[KEY_MENU_RIGHT]) + { + SDWORD newpos = VidGetPosition (); + if (PulsedInputState.menu[KEY_MENU_LEFT]) + newpos -= 2000; + else if (PulsedInputState.menu[KEY_MENU_RIGHT]) + newpos += 1000; + if (newpos < 0) + newpos = 0; + + VidSeek (newpos); + } + else + { + SleepThread (ONE_SECOND / 30); + } + + return TRUE; +} + +static void +FadeClearScreen (void) +{ + BYTE xform_buf[1]; + RECT r = {{0, 0}, {SCREEN_WIDTH, SCREEN_HEIGHT}}; + + xform_buf[0] = FadeAllToBlack; + SleepThreadUntil (XFormColorMap ( + (COLORMAPPTR) xform_buf, ONE_SECOND / 2)); + + // paint black rect over screen + LockMutex (GraphicsLock); + SetContext (ScreenContext); + SetContextForeGroundColor ( + BUILD_COLOR (MAKE_RGB15 (0x00, 0x00, 0x00), 0x00)); + DrawFilledRectangle (&r); + UnlockMutex (GraphicsLock); + + // fade in black rect instantly + xform_buf[0] = FadeAllToColor; + XFormColorMap ((COLORMAPPTR) xform_buf, 0); +} + +static BOOLEAN +ShowLegacyVideo (LEGACY_VIDEO vid) +{ + VIDEO_INPUT_STATE vis; + LEGACY_VIDEO_REF ref; + + FadeClearScreen (); + + ref = PlayLegacyVideo (vid); + if (!ref) + return FALSE; + + // XXX: FlushInput() won't be need once DoInput(reset-input) works right + FlushInput (); + vis.MenuRepeatDelay = 0; + vis.InputFunc = DoVideoInput; + vis.CurVideo = ref; + SetMenuSounds (MENU_SOUND_NONE, MENU_SOUND_NONE); + DoInput (&vis, TRUE); + + StopLegacyVideo (ref); + FadeClearScreen (); + + return TRUE; +} + BOOLEAN ShowPresentation (RESOURCE res) { @@ -816,13 +915,15 @@ ShowPresentation (RESOURCE res) } if (!strcmp (resType, "STRTAB")) { - return ShowSlidePresentation (CaptureStringTable ( - LoadStringTable (res))); + STRING pres = CaptureStringTable (LoadStringTable (res)); + BOOLEAN result = ShowSlidePresentation (pres); + DestroyStringTable (ReleaseStringTable (pres)); + return result; } else if (!strcmp (resType, "3DOVID")) { LEGACY_VIDEO vid = LoadLegacyVideoInstance (res); - BOOLEAN result = PlayLegacyVideo (vid); + BOOLEAN result = ShowLegacyVideo (vid); DestroyLegacyVideo (vid); return result; }