2007-07-30 15:53:38 +00:00
|
|
|
/* ScummVM - Graphic Adventure Engine
|
|
|
|
*
|
|
|
|
* ScummVM is the legal property of its developers, whose names
|
|
|
|
* are too numerous to list here. Please refer to the COPYRIGHT
|
|
|
|
* file distributed with this source distribution.
|
|
|
|
*
|
|
|
|
* 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
|
2008-01-05 12:45:14 +00:00
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
2007-07-30 15:53:38 +00:00
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
*
|
|
|
|
* $URL$
|
|
|
|
* $Id$
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2008-07-08 00:16:55 +00:00
|
|
|
|
2007-07-30 15:53:38 +00:00
|
|
|
#include "gob/videoplayer.h"
|
2009-05-21 17:12:33 +00:00
|
|
|
#include "gob/helper.h"
|
2007-07-30 15:53:38 +00:00
|
|
|
#include "gob/global.h"
|
|
|
|
#include "gob/dataio.h"
|
|
|
|
#include "gob/video.h"
|
|
|
|
#include "gob/game.h"
|
|
|
|
#include "gob/palanim.h"
|
|
|
|
#include "gob/inter.h"
|
2008-04-27 03:19:19 +00:00
|
|
|
#include "gob/map.h"
|
2008-05-08 15:51:02 +00:00
|
|
|
#include "gob/sound/sound.h"
|
2007-07-30 15:53:38 +00:00
|
|
|
|
|
|
|
namespace Gob {
|
|
|
|
|
2010-08-08 00:35:18 +00:00
|
|
|
VideoPlayer::Properties::Properties() : type(kVideoTypeTry), sprite(Draw::kFrontSurface),
|
2010-08-08 00:34:33 +00:00
|
|
|
x(-1), y(-1), width(-1), height(-1), flags(kFlagFrontSurface),
|
2010-08-08 00:37:19 +00:00
|
|
|
startFrame(-1), lastFrame(-1), endFrame(-1), breakKey(kShortKeyEscape),
|
|
|
|
palCmd(8), palStart(0), palEnd(255), palFrame(-1), fade(false), canceled(false) {
|
2010-08-08 00:34:33 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
VideoPlayer::Video::Video() : decoder(0) {
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VideoPlayer::Video::isEmpty() const {
|
|
|
|
return decoder == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VideoPlayer::Video::close() {
|
|
|
|
delete decoder;
|
|
|
|
|
|
|
|
decoder = 0;
|
|
|
|
fileName.clear();
|
2010-08-08 00:35:50 +00:00
|
|
|
surface.reset();
|
2010-08-08 00:34:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-03-11 06:15:23 +00:00
|
|
|
const char *VideoPlayer::_extensions[] = { "IMD", "IMD", "VMD", "RMD", "SMD" };
|
2007-07-30 15:53:38 +00:00
|
|
|
|
2010-08-08 00:37:19 +00:00
|
|
|
VideoPlayer::VideoPlayer(GobEngine *vm) : _vm(vm), _needBlit(false),
|
2010-08-08 00:33:59 +00:00
|
|
|
_noCursorSwitch(false), _woodruffCohCottWorkaround(false) {
|
2007-07-30 15:53:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
VideoPlayer::~VideoPlayer() {
|
2010-08-08 00:33:59 +00:00
|
|
|
for (int i = 0; i < kVideoSlotCount; i++)
|
2010-08-08 00:34:33 +00:00
|
|
|
_videoSlots[i].close();
|
2007-07-30 15:53:38 +00:00
|
|
|
}
|
|
|
|
|
2010-08-08 00:34:33 +00:00
|
|
|
int VideoPlayer::openVideo(bool primary, const Common::String &file, Properties &properties) {
|
|
|
|
int slot = 0;
|
|
|
|
|
|
|
|
Video *video = 0;
|
|
|
|
if (!primary) {
|
|
|
|
slot = getNextFreeSlot();
|
|
|
|
if (slot < 0) {
|
|
|
|
warning("VideoPlayer::openVideo(): Can't open video \"%s\": No free slot", file.c_str());
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
video = &_videoSlots[slot];
|
|
|
|
} else
|
|
|
|
video = &_videoSlots[0];
|
|
|
|
|
|
|
|
// Different video already in the slot => close that video
|
|
|
|
if (!video->isEmpty() && (video->fileName.compareToIgnoreCase(file) != 0))
|
|
|
|
video->close();
|
|
|
|
|
|
|
|
// No video => load the requested file
|
|
|
|
if (video->isEmpty()) {
|
|
|
|
// Open the video
|
|
|
|
if (!(video->decoder = openVideo(file, properties)))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
// Set the filename
|
|
|
|
video->fileName = file;
|
2010-08-08 00:35:50 +00:00
|
|
|
|
|
|
|
// WORKAROUND: In some rare cases, the cursor should still be
|
|
|
|
// displayed while a video is playing.
|
|
|
|
_noCursorSwitch = false;
|
|
|
|
if (primary && (_vm->getGameType() == kGameTypeLostInTime)) {
|
|
|
|
if (!file.compareToIgnoreCase("PORTA03.IMD") ||
|
|
|
|
!file.compareToIgnoreCase("PORTA03A.IMD") ||
|
|
|
|
!file.compareToIgnoreCase("CALE1.IMD") ||
|
|
|
|
!file.compareToIgnoreCase("AMIL2.IMD") ||
|
|
|
|
!file.compareToIgnoreCase("AMIL3B.IMD") ||
|
|
|
|
!file.compareToIgnoreCase("DELB.IMD"))
|
|
|
|
_noCursorSwitch = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// WORKAROUND: In Woodruff, Coh Cott vanished in one video on her party.
|
|
|
|
// This is a bug in video, so we work around it.
|
|
|
|
_woodruffCohCottWorkaround = false;
|
|
|
|
if (primary && (_vm->getGameType() == kGameTypeWoodruff)) {
|
|
|
|
if (!file.compareToIgnoreCase("SQ32-03.VMD"))
|
|
|
|
_woodruffCohCottWorkaround = true;
|
|
|
|
}
|
2009-10-18 17:28:02 +00:00
|
|
|
}
|
2007-08-13 14:04:50 +00:00
|
|
|
|
2010-08-08 00:35:50 +00:00
|
|
|
if (!(properties.flags & kFlagNoVideo) && (properties.sprite >= 0)) {
|
2010-08-08 00:37:19 +00:00
|
|
|
bool ownSurf = (properties.sprite != Draw::kFrontSurface) && (properties.sprite != Draw::kBackSurface);
|
2010-08-08 00:35:50 +00:00
|
|
|
bool screenSize = properties.flags & kFlagScreenSurface;
|
|
|
|
|
|
|
|
if (ownSurf) {
|
|
|
|
_vm->_draw->_spritesArray[properties.sprite] =
|
|
|
|
_vm->_video->initSurfDesc(_vm->_global->_videoMode,
|
|
|
|
screenSize ? _vm->_width : video->decoder->getWidth(),
|
|
|
|
screenSize ? _vm->_height : video->decoder->getHeight(), 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!_vm->_draw->_spritesArray[properties.sprite]) {
|
2010-08-08 00:37:19 +00:00
|
|
|
properties.sprite = -1;
|
2010-08-08 00:35:50 +00:00
|
|
|
video->surface.reset();
|
2010-08-08 00:37:52 +00:00
|
|
|
video->decoder->setSurfaceMemory();
|
2010-08-08 00:35:50 +00:00
|
|
|
} else {
|
|
|
|
video->surface = _vm->_draw->_spritesArray[properties.sprite];
|
2010-08-08 00:37:52 +00:00
|
|
|
video->decoder->setSurfaceMemory(video->surface->getVidMem(),
|
|
|
|
video->surface->getWidth(), video->surface->getHeight(), 1);
|
2010-08-08 00:35:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
2010-08-08 00:37:19 +00:00
|
|
|
properties.sprite = -1;
|
2010-08-08 00:35:50 +00:00
|
|
|
video->surface.reset();
|
2010-08-08 00:37:52 +00:00
|
|
|
video->decoder->setSurfaceMemory();
|
2010-08-08 00:35:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (primary)
|
|
|
|
_needBlit = (properties.flags & kFlagUseBackSurfaceContent) && (properties.sprite == Draw::kFrontSurface);
|
|
|
|
|
|
|
|
// video->decoder->setFrameRate(_vm->_util->getFrameRate());
|
|
|
|
// video->decoder->setXY(x, y);
|
2010-08-08 00:34:33 +00:00
|
|
|
|
2010-08-08 00:35:50 +00:00
|
|
|
WRITE_VAR(7, video->decoder->getFrameCount());
|
|
|
|
|
|
|
|
return slot;
|
2010-08-08 00:34:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool VideoPlayer::closeVideo(int slot) {
|
|
|
|
Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
video->close();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2010-08-08 00:37:19 +00:00
|
|
|
bool VideoPlayer::play(int slot, Properties &properties) {
|
2010-08-08 00:34:33 +00:00
|
|
|
Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return false;
|
|
|
|
|
2010-08-08 00:37:19 +00:00
|
|
|
bool primary = slot == 0;
|
2010-08-08 00:34:33 +00:00
|
|
|
|
2010-08-08 00:37:19 +00:00
|
|
|
// NOTE: For testing (and comfort?) purposes, we enable aborting of all videos)
|
|
|
|
properties.breakKey = kShortKeyEscape;
|
|
|
|
|
|
|
|
if (properties.startFrame < 0)
|
|
|
|
properties.startFrame = video->decoder->getCurFrame() + 1;
|
|
|
|
if (properties.lastFrame < 0)
|
|
|
|
properties.lastFrame = video->decoder->getFrameCount();
|
|
|
|
if (properties.endFrame < 0)
|
|
|
|
properties.endFrame = properties.lastFrame;
|
|
|
|
if (properties.palFrame < 0)
|
|
|
|
properties.palFrame = properties.startFrame;
|
|
|
|
|
|
|
|
properties.startFrame--;
|
|
|
|
properties.lastFrame--;
|
|
|
|
properties.endFrame--;
|
|
|
|
properties.palFrame--;
|
|
|
|
|
|
|
|
properties.palCmd &= 0x3F;
|
|
|
|
|
|
|
|
if (primary) {
|
|
|
|
_vm->_draw->_showCursor = _noCursorSwitch ? 3 : 0;
|
|
|
|
|
|
|
|
if (properties.fade)
|
|
|
|
_vm->_palAnim->fade(0, -2, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool backwards = properties.startFrame > properties.lastFrame;
|
|
|
|
|
|
|
|
properties.canceled = false;
|
|
|
|
|
|
|
|
while ((properties.startFrame != properties.lastFrame) && !properties.canceled) {
|
|
|
|
if (!playFrame(slot, properties))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
properties.startFrame += backwards ? -1 : 1;
|
|
|
|
|
|
|
|
evalBgShading(*video);
|
|
|
|
|
|
|
|
if (primary && properties.fade) {
|
|
|
|
_vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
|
|
|
|
properties.fade = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
_vm->_util->longDelay(100);
|
|
|
|
/*if (!_noCursorSwitch)
|
|
|
|
video.waitEndFrame();*/
|
|
|
|
}
|
|
|
|
|
|
|
|
evalBgShading(*video);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VideoPlayer::playFrame(int slot, Properties &properties) {
|
|
|
|
Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
bool primary = slot == 0;
|
|
|
|
|
|
|
|
if (video->decoder->getCurFrame() != properties.startFrame);
|
|
|
|
video->decoder->seek(properties.startFrame + 1);
|
|
|
|
|
|
|
|
bool modifiedPal = false;
|
|
|
|
|
|
|
|
if (primary) {
|
|
|
|
// Pre-decoding palette and blitting, only for primary videos
|
|
|
|
|
|
|
|
if ((properties.startFrame == properties.palFrame) ||
|
|
|
|
((properties.startFrame == properties.endFrame) && (properties.palCmd == 8))) {
|
|
|
|
|
|
|
|
modifiedPal = true;
|
|
|
|
_vm->_draw->_applyPal = true;
|
|
|
|
|
|
|
|
if (properties.palCmd >= 4)
|
|
|
|
; // copyPalette(video, palStart, palEnd);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (modifiedPal && (properties.palCmd == 8) && (properties.sprite != Draw::kBackSurface))
|
|
|
|
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
|
|
|
|
|
|
|
|
if (_needBlit)
|
|
|
|
_vm->_draw->forceBlit();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Graphics::Surface *surface = video->decoder->decodeNextFrame();
|
|
|
|
if (!surface)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
WRITE_VAR(11, video->decoder->getCurFrame());
|
|
|
|
|
2010-08-08 00:37:52 +00:00
|
|
|
// blitFrame(video->surface, *surface);
|
2010-08-08 00:37:19 +00:00
|
|
|
|
|
|
|
if (_woodruffCohCottWorkaround && (properties.startFrame == 31)) {
|
|
|
|
// WORKAROUND: This frame mistakenly masks Coh Cott, making her vanish
|
|
|
|
// To prevent that, we'll never draw that part
|
|
|
|
// state.left += 50;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (primary) {
|
|
|
|
// Post-decoding palette and blitting, only for primary videos
|
|
|
|
|
|
|
|
if (_needBlit)
|
|
|
|
_vm->_draw->forceBlit(true);
|
|
|
|
|
|
|
|
if (modifiedPal && (properties.palCmd == 16)) {
|
|
|
|
if (properties.sprite == Draw::kBackSurface)
|
|
|
|
_vm->_draw->forceBlit();
|
|
|
|
_vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
|
|
|
|
_vm->_draw->_noInvalidated = true;
|
|
|
|
_vm->_video->dirtyRectsAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
if ((state.flags & Graphics::CoktelDecoder::kStatePalette) && (palCmd > 1)) {
|
|
|
|
copyPalette(video, palStart, palEnd);
|
|
|
|
|
|
|
|
if (!_backSurf)
|
|
|
|
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
|
|
|
|
else
|
|
|
|
_vm->_draw->_applyPal = true;
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (modifiedPal && (properties.palCmd == 8) && (properties.sprite == Draw::kBackSurface))
|
|
|
|
_vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
|
|
|
|
|
|
|
|
if (properties.sprite == Draw::kBackSurface) {
|
|
|
|
|
|
|
|
_vm->_draw->invalidateRect(0, 0, video->decoder->getWidth(), video->decoder->getHeight());
|
|
|
|
_vm->_draw->blitInvalidated();
|
|
|
|
|
|
|
|
// if (!noRetrace)
|
|
|
|
_vm->_video->retrace();
|
|
|
|
|
|
|
|
} else if (properties.sprite == Draw::kFrontSurface) {
|
|
|
|
_vm->_video->dirtyRectsAdd(0, 0, video->decoder->getWidth(), video->decoder->getHeight());
|
|
|
|
|
|
|
|
// if (!noRetrace)
|
|
|
|
_vm->_video->retrace();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
// Subtitle
|
|
|
|
if (state.flags & Graphics::CoktelDecoder::kStateSpeech)
|
|
|
|
_vm->_draw->printTotText(state.speechId);
|
|
|
|
*/
|
|
|
|
|
|
|
|
if (modifiedPal && ((properties.palCmd == 2) || (properties.palCmd == 4)))
|
|
|
|
_vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (primary)
|
|
|
|
checkAbort(*video, properties);
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void VideoPlayer::checkAbort(Video &video, Properties &properties) {
|
|
|
|
_vm->_util->processInput();
|
|
|
|
|
|
|
|
if (_vm->shouldQuit()) {
|
|
|
|
// video.decoder->disableSound();
|
|
|
|
|
|
|
|
properties.canceled = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (properties.breakKey != 0) {
|
|
|
|
_vm->_util->getMouseState(&_vm->_global->_inter_mouseX,
|
|
|
|
&_vm->_global->_inter_mouseY, &_vm->_game->_mouseButtons);
|
|
|
|
|
|
|
|
_vm->_inter->storeKey(_vm->_util->checkKey());
|
|
|
|
if (VAR(0) == (unsigned) properties.breakKey) {
|
|
|
|
// video.decoder->disableSound();
|
|
|
|
|
|
|
|
// Seek to the last frame. Some scripts depend on that.
|
|
|
|
video.decoder->seek(properties.endFrame + 1, SEEK_SET, true);
|
|
|
|
|
|
|
|
properties.canceled = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void VideoPlayer::blitFrame(SurfaceDescPtr dst, const Graphics::Surface &src) {
|
|
|
|
if (!dst || !src.pixels)
|
|
|
|
return;
|
|
|
|
|
|
|
|
uint32 w = MIN<uint32>(dst->getWidth() , src.w);
|
|
|
|
uint32 h = MIN<uint32>(dst->getHeight(), src.h);
|
|
|
|
|
|
|
|
byte *d = dst->getVidMem();
|
|
|
|
const byte *s = (const byte *) src.pixels;
|
|
|
|
|
|
|
|
while (h-- > 0) {
|
|
|
|
memcpy(d, s, w);
|
|
|
|
|
|
|
|
d += dst->getWidth();
|
|
|
|
s += src.pitch;
|
|
|
|
}
|
2010-08-08 00:34:33 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool VideoPlayer::slotIsOpen(int slot) const {
|
|
|
|
return getVideoBySlot(slot) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Common::String VideoPlayer::getFileName(int slot) const {
|
|
|
|
const Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return "";
|
|
|
|
|
|
|
|
return video->fileName;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16 VideoPlayer::getFlags(int slot) const {
|
|
|
|
const Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 0; // video->decoder->getFlags();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 VideoPlayer::getFrameCount(int slot) const {
|
|
|
|
const Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return video->decoder->getFrameCount();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 VideoPlayer::getCurrentFrame(int slot) const {
|
|
|
|
const Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return video->decoder->getCurFrame();
|
|
|
|
}
|
2007-07-30 15:53:38 +00:00
|
|
|
|
2010-08-08 00:34:33 +00:00
|
|
|
uint16 VideoPlayer::getWidth(int slot) const {
|
|
|
|
const Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return video->decoder->getWidth();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16 VideoPlayer::getHeight(int slot) const {
|
|
|
|
const Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return video->decoder->getHeight();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16 VideoPlayer::getDefaultX(int slot) const {
|
|
|
|
const Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 0; // video->decoder->getDefaultX();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint16 VideoPlayer::getDefaultY(int slot) const {
|
|
|
|
const Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 0; // video->decoder->getDefaultY();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint32 VideoPlayer::getFeatures(int slot) const {
|
|
|
|
const Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 0; // video->decoder->getFeatures();
|
|
|
|
}
|
|
|
|
|
|
|
|
void VideoPlayer::getState(int slot) const {
|
|
|
|
const Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return;
|
|
|
|
|
|
|
|
return; // video->decoder->getState();
|
|
|
|
}
|
|
|
|
|
|
|
|
bool VideoPlayer::hasExtraData(const Common::String &fileName, int slot) const {
|
|
|
|
const Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return false; // video->decoder->hasExtraData(fileName);
|
|
|
|
}
|
|
|
|
|
|
|
|
Common::MemoryReadStream *VideoPlayer::getExtraData(const Common::String &fileName, int slot) {
|
|
|
|
const Video *video = getVideoBySlot(slot);
|
|
|
|
if (!video)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return 0; // video->decoder->getExtraData(fileName);
|
|
|
|
}
|
|
|
|
|
2010-08-08 00:37:19 +00:00
|
|
|
void VideoPlayer::writeVideoInfo(const Common::String &file, int16 varX, int16 varY,
|
|
|
|
int16 varFrames, int16 varWidth, int16 varHeight) {
|
|
|
|
|
|
|
|
Properties properties;
|
|
|
|
|
|
|
|
int slot = openVideo(false, file, properties);
|
|
|
|
if (slot >= 0) {
|
|
|
|
Video &video = _videoSlots[slot];
|
|
|
|
|
|
|
|
int16 x = -1, y = -1, width = -1, height = -1;
|
|
|
|
|
|
|
|
// x = video.decoder->getX();
|
|
|
|
// y = video.decoder->getY();
|
|
|
|
width = video.decoder->getWidth();
|
|
|
|
width = video.decoder->getHeight();
|
|
|
|
|
|
|
|
/*
|
|
|
|
if (VAR_OFFSET(varX) == 0xFFFFFFFF)
|
|
|
|
video.decoder->getFrameCoords(1, x, y, width, height);
|
|
|
|
*/
|
|
|
|
|
|
|
|
WRITE_VAR_OFFSET(varX , x);
|
|
|
|
WRITE_VAR_OFFSET(varY , y);
|
|
|
|
WRITE_VAR_OFFSET(varFrames, video.decoder->getFrameCount());
|
|
|
|
WRITE_VAR_OFFSET(varWidth , width);
|
|
|
|
WRITE_VAR_OFFSET(varHeight, height);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
WRITE_VAR_OFFSET(varX , (uint32) -1);
|
|
|
|
WRITE_VAR_OFFSET(varY , (uint32) -1);
|
|
|
|
WRITE_VAR_OFFSET(varFrames, (uint32) -1);
|
|
|
|
WRITE_VAR_OFFSET(varWidth , (uint32) -1);
|
|
|
|
WRITE_VAR_OFFSET(varHeight, (uint32) -1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-08-08 00:34:33 +00:00
|
|
|
const VideoPlayer::Video *VideoPlayer::getVideoBySlot(int slot) const {
|
|
|
|
if ((slot < 0) || (slot >= kVideoSlotCount))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (_videoSlots[slot].isEmpty())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return &_videoSlots[slot];
|
|
|
|
}
|
|
|
|
|
|
|
|
VideoPlayer::Video *VideoPlayer::getVideoBySlot(int slot) {
|
|
|
|
if ((slot < 0) || (slot >= kVideoSlotCount))
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
if (_videoSlots[slot].isEmpty())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
return &_videoSlots[slot];
|
|
|
|
}
|
|
|
|
|
|
|
|
int VideoPlayer::getNextFreeSlot() {
|
|
|
|
// Starting with 1, since 0 is reserved for the "primary" video
|
|
|
|
for (int i = 1; i < kVideoSlotCount; i++)
|
|
|
|
if (_videoSlots[i].isEmpty())
|
|
|
|
return i;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2010-08-08 00:37:19 +00:00
|
|
|
void VideoPlayer::evalBgShading(Video &video) {
|
|
|
|
/*
|
|
|
|
if (video.isSoundPlaying())
|
|
|
|
_vm->_sound->bgShade();
|
|
|
|
else
|
|
|
|
_vm->_sound->bgUnshade();
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
2010-08-08 00:34:33 +00:00
|
|
|
Common::String VideoPlayer::findFile(const Common::String &file, Properties &properties) {
|
|
|
|
|
|
|
|
bool hasExtension = false;
|
|
|
|
|
|
|
|
Common::String base = file;
|
|
|
|
Common::String fileName = file;
|
|
|
|
|
|
|
|
const char *posDot = strrchr(base.c_str(), '.');
|
|
|
|
if (posDot) {
|
|
|
|
hasExtension = true;
|
|
|
|
base = Common::String(base.c_str(), posDot);
|
|
|
|
posDot++;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (hasExtension) {
|
2007-07-30 15:53:38 +00:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAYSIZE(_extensions); i++) {
|
2010-08-08 00:34:33 +00:00
|
|
|
if (!scumm_stricmp(posDot, _extensions[i])) {
|
|
|
|
if ((properties.type != kVideoTypeTry) && (properties.type == ((Type) i))) {
|
|
|
|
warning("Attempted to open video \"%s\", but requested a different type", fileName.c_str());
|
|
|
|
return "";
|
2007-07-30 15:53:38 +00:00
|
|
|
}
|
2010-08-08 00:34:33 +00:00
|
|
|
properties.type = (Type) i;
|
2007-07-30 15:53:38 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (i >= ARRAYSIZE(_extensions))
|
2010-08-08 00:34:33 +00:00
|
|
|
hasExtension = false;
|
2007-07-30 15:53:38 +00:00
|
|
|
}
|
|
|
|
|
2010-08-08 00:34:33 +00:00
|
|
|
if (!hasExtension) {
|
2007-07-30 15:53:38 +00:00
|
|
|
// No or unrecognized extension. Probing.
|
|
|
|
|
|
|
|
int i;
|
|
|
|
for (i = 0; i < ARRAYSIZE(_extensions); i++) {
|
2010-08-08 00:34:33 +00:00
|
|
|
if ((properties.type == kVideoTypeTry) || (properties.type == ((Type) i))) {
|
|
|
|
fileName = base + "." + _extensions[i];
|
2007-07-30 15:53:38 +00:00
|
|
|
|
2010-08-08 00:34:33 +00:00
|
|
|
if (_vm->_dataIO->existData(fileName.c_str())) {
|
|
|
|
properties.type = (Type) i;
|
2007-07-30 15:53:38 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-08-08 00:34:33 +00:00
|
|
|
if ((i >= ARRAYSIZE(_extensions)) || (properties.type == kVideoTypeTry)) {
|
|
|
|
warning("Couldn't open video \"%s\"", file.c_str());
|
|
|
|
return "";
|
2007-07-30 15:53:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2010-08-08 00:34:33 +00:00
|
|
|
return fileName;
|
2008-04-27 03:19:19 +00:00
|
|
|
}
|
2007-07-30 15:53:38 +00:00
|
|
|
|
2010-08-08 00:34:33 +00:00
|
|
|
Graphics::CoktelDecoder *VideoPlayer::openVideo(const Common::String &file, Properties &properties) {
|
|
|
|
Common::String fileName = findFile(file, properties);
|
|
|
|
if (fileName.empty())
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
Common::SeekableReadStream *stream = _vm->_dataIO->getDataStream(fileName.c_str());
|
2010-08-08 00:33:59 +00:00
|
|
|
if (!stream)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
Graphics::CoktelDecoder *video = 0;
|
2010-08-08 00:34:33 +00:00
|
|
|
if (properties.type == kVideoTypeIMD)
|
2010-08-08 00:33:59 +00:00
|
|
|
warning("TODO: IMD");
|
|
|
|
//_video = new Graphics::Imd();
|
2010-08-08 00:34:33 +00:00
|
|
|
else if (properties.type == kVideoTypePreIMD) {
|
|
|
|
warning("PreIMDDecoder \"%s\" %dx%d", fileName.c_str(), properties.width, properties.height);
|
|
|
|
video = new Graphics::PreIMDDecoder(properties.width, properties.height, *_vm->_mixer, Audio::Mixer::kSFXSoundType);
|
|
|
|
} else if (properties.type == kVideoTypeVMD)
|
2010-08-08 00:33:59 +00:00
|
|
|
warning("TODO: VMD");
|
|
|
|
//_video = new Graphics::Vmd(_vm->_video->_palLUT);
|
2010-08-08 00:34:33 +00:00
|
|
|
else if (properties.type == kVideoTypeRMD)
|
2010-08-08 00:33:59 +00:00
|
|
|
warning("TODO: RMD");
|
|
|
|
//_video = new Graphics::Vmd(_vm->_video->_palLUT);
|
|
|
|
else
|
2010-08-08 00:34:33 +00:00
|
|
|
warning("Couldn't open video \"%s\": Invalid video Type", fileName.c_str());
|
2010-08-08 00:33:59 +00:00
|
|
|
|
|
|
|
if (!video) {
|
|
|
|
delete stream;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!video->load(*stream)) {
|
|
|
|
delete video;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return video;
|
|
|
|
}
|
|
|
|
|
2010-08-08 00:34:33 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Obsolete, to be deleted
|
|
|
|
|
2008-04-27 03:19:19 +00:00
|
|
|
bool VideoPlayer::primaryOpen(const char *videoFile, int16 x, int16 y,
|
2010-03-11 06:15:23 +00:00
|
|
|
int32 flags, Type which, int16 width, int16 height) {
|
2007-07-30 15:53:38 +00:00
|
|
|
|
2010-08-08 00:34:33 +00:00
|
|
|
return false;
|
2007-07-30 15:53:38 +00:00
|
|
|
}
|
|
|
|
|
2009-04-29 19:58:43 +00:00
|
|
|
bool VideoPlayer::primaryPlay(int16 startFrame, int16 lastFrame, int16 breakKey,
|
2007-07-30 15:53:38 +00:00
|
|
|
uint16 palCmd, int16 palStart, int16 palEnd,
|
2008-12-14 03:08:02 +00:00
|
|
|
int16 palFrame, int16 endFrame, bool fade, int16 reverseTo, bool forceSeek) {
|
2007-07-30 15:53:38 +00:00
|
|
|
|
2010-08-08 00:34:33 +00:00
|
|
|
return false;
|
2007-07-30 15:53:38 +00:00
|
|
|
}
|
|
|
|
|
2008-04-27 03:19:19 +00:00
|
|
|
void VideoPlayer::primaryClose() {
|
|
|
|
}
|
|
|
|
|
2010-03-11 06:15:23 +00:00
|
|
|
int VideoPlayer::slotOpen(const char *videoFile, Type which, int16 width, int16 height) {
|
2010-08-08 00:34:33 +00:00
|
|
|
return -1;
|
2008-04-27 03:19:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void VideoPlayer::slotPlay(int slot, int16 frame) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void VideoPlayer::slotClose(int slot) {
|
|
|
|
}
|
|
|
|
|
|
|
|
void VideoPlayer::slotCopyFrame(int slot, byte *dest,
|
|
|
|
uint16 left, uint16 top, uint16 width, uint16 height,
|
|
|
|
uint16 x, uint16 y, uint16 pitch, int16 transp) {
|
|
|
|
|
2010-08-08 00:34:33 +00:00
|
|
|
#if 0
|
2010-08-08 00:33:59 +00:00
|
|
|
if ((slot < 0) || (slot >= kVideoSlotCount) || !_videoSlots[slot])
|
2008-04-27 03:19:19 +00:00
|
|
|
return;
|
|
|
|
|
2010-08-08 00:33:59 +00:00
|
|
|
/*_videoSlots[slot]->getVideo()->copyCurrentFrame(dest,
|
|
|
|
left, top, width, height, x, y, pitch, transp);*/
|
2010-08-08 00:34:33 +00:00
|
|
|
#endif
|
2008-04-27 03:19:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void VideoPlayer::slotCopyPalette(int slot, int16 palStart, int16 palEnd) {
|
2010-08-08 00:34:33 +00:00
|
|
|
#if 0
|
2010-08-08 00:33:59 +00:00
|
|
|
if ((slot < 0) || (slot >= kVideoSlotCount) || !_videoSlots[slot])
|
2008-04-27 03:19:19 +00:00
|
|
|
return;
|
|
|
|
|
2010-08-08 00:33:59 +00:00
|
|
|
//copyPalette(*(_videoSlots[slot]->getVideo()), palStart, palEnd);
|
2010-08-08 00:34:33 +00:00
|
|
|
#endif
|
2008-04-27 03:19:19 +00:00
|
|
|
}
|
|
|
|
|
2008-05-07 03:49:53 +00:00
|
|
|
void VideoPlayer::slotWaitEndFrame(int slot, bool onlySound) {
|
2010-08-08 00:34:33 +00:00
|
|
|
#if 0
|
2010-08-08 00:33:59 +00:00
|
|
|
Graphics::CoktelDecoder *video = getVideoBySlot(slot);
|
2008-05-07 03:49:53 +00:00
|
|
|
|
2009-06-06 19:06:47 +00:00
|
|
|
if (video) {
|
2010-08-08 00:33:59 +00:00
|
|
|
/*
|
|
|
|
Graphics::CoktelDecoder &cVideo = *video->getVideo();
|
2008-05-07 03:49:53 +00:00
|
|
|
|
2010-08-08 00:33:59 +00:00
|
|
|
if (!onlySound || (cVideo.getFeatures() & Graphics::CoktelDecoder::kFeaturesSound))
|
2009-06-06 19:06:47 +00:00
|
|
|
cVideo.waitEndFrame();
|
2010-08-08 00:33:59 +00:00
|
|
|
*/
|
2009-06-06 19:06:47 +00:00
|
|
|
}
|
2010-08-08 00:34:33 +00:00
|
|
|
#endif
|
2008-04-27 03:19:19 +00:00
|
|
|
}
|
|
|
|
|
2009-04-24 21:30:40 +00:00
|
|
|
void VideoPlayer::slotSetDoubleMode(int slot, bool doubleMode) {
|
2009-04-29 19:58:43 +00:00
|
|
|
}
|
|
|
|
|
2010-08-08 00:33:59 +00:00
|
|
|
void VideoPlayer::copyPalette(Graphics::CoktelDecoder &video, int16 palStart, int16 palEnd) {
|
|
|
|
/*
|
|
|
|
if (!(video.getFeatures() & Graphics::CoktelDecoder::kFeaturesPalette))
|
2008-12-05 18:47:50 +00:00
|
|
|
return;
|
2010-08-08 00:33:59 +00:00
|
|
|
*/
|
2008-12-05 18:47:50 +00:00
|
|
|
|
2008-06-19 22:54:17 +00:00
|
|
|
if (palStart < 0)
|
|
|
|
palStart = 0;
|
|
|
|
if (palEnd < 0)
|
|
|
|
palEnd = 255;
|
|
|
|
|
2010-08-08 00:33:59 +00:00
|
|
|
/*
|
2010-05-17 22:46:53 +00:00
|
|
|
memcpy(((char *)(_vm->_global->_pPaletteDesc->vgaPal)) + palStart * 3,
|
2008-06-19 22:54:17 +00:00
|
|
|
video.getPalette() + palStart * 3,
|
|
|
|
(palEnd - palStart + 1) * 3);
|
2010-08-08 00:33:59 +00:00
|
|
|
*/
|
2007-07-30 15:53:38 +00:00
|
|
|
}
|
|
|
|
|
2010-08-08 00:33:59 +00:00
|
|
|
void VideoPlayer::evalBgShading(Graphics::CoktelDecoder &video) {
|
|
|
|
/*
|
2008-05-08 15:51:02 +00:00
|
|
|
if (video.isSoundPlaying())
|
|
|
|
_vm->_sound->bgShade();
|
|
|
|
else
|
|
|
|
_vm->_sound->bgUnshade();
|
2010-08-08 00:33:59 +00:00
|
|
|
*/
|
2008-05-08 15:51:02 +00:00
|
|
|
}
|
|
|
|
|
2007-07-30 15:53:38 +00:00
|
|
|
} // End of namespace Gob
|