Logo Search packages:      
Sourcecode: scummvm version File versions  Download package

videoplayer.cpp

/* 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
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.      See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 * $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-0-11-1/engines/gob/videoplayer.cpp $
 * $Id: videoplayer.cpp 30944 2008-02-23 22:50:18Z sev $
 *
 */

#include "gob/videoplayer.h"
#include "gob/global.h"
#include "gob/util.h"
#include "gob/dataio.h"
#include "gob/video.h"
#include "gob/draw.h"
#include "gob/game.h"
#include "gob/palanim.h"
#include "gob/inter.h"

namespace Gob {

const char *VideoPlayer::_extensions[] = { "IMD", "VMD" };

VideoPlayer::VideoPlayer(GobEngine *vm) : _vm(vm) {
      _curFile[0] = 0;
      _stream = 0;
      _video = 0;
      _backSurf = false;
}

VideoPlayer::~VideoPlayer() {
      closeVideo();
}

bool VideoPlayer::openVideo(const char *video, int16 x, int16 y, int16 flags, Type which) {
      char fileName[256];

      strncpy0(fileName, video, 250);

      char *extStart = strrchr(fileName, '.');
      // There's no empty extension
      if (extStart == (fileName + strlen(fileName) - 1)) {
            *extStart = 0;
            extStart = 0;
      }

      if (extStart) {
            // The requested file already has an extension. Verifying.

            int i;
            for (i = 0; i < ARRAYSIZE(_extensions); i++) {
                  if (!scumm_stricmp(extStart + 1, _extensions[i])) {
                        if ((which != kVideoTypeTry) && (which == ((Type) i))) {
                              warning("Attempted to open video \"%s\", "
                                          "but requested a different type", fileName);
                              return false;
                        }
                        which = (Type) i;
                        break;
                  }
            }
            if (i >= ARRAYSIZE(_extensions))
                  extStart = 0;

      }

      if (!extStart) {
            // No or unrecognized extension. Probing.

            int len = strlen(fileName);

            int i;
            for (i = 0; i < ARRAYSIZE(_extensions); i++) {
                  if ((which == kVideoTypeTry) || (which == ((Type) i))) {
                        int16 handle;

                        fileName[len] = '.';
                        fileName[len + 1] = 0;
                        strcat(fileName, _extensions[i]);

                        handle = _vm->_dataIO->openData(fileName);
                        if (handle >= 0) {
                              _vm->_dataIO->closeData(handle);
                              which = (Type) i;
                              break;
                        }
                  }
            }
            if ((i >= ARRAYSIZE(_extensions)) || (which == kVideoTypeTry)) {
                  fileName[len] = 0;
                  warning("Couldn't open video \"%s\"", fileName);
                  return false;
            }

      }

      if (scumm_strnicmp(_curFile, fileName, strlen(fileName))) {
            closeVideo();

            int16 handle = _vm->_dataIO->openData(fileName);

            if (handle < 0) {
                  warning("Couldn't open video \"%s\": No such file", fileName);
                  return false;
            }

            _stream = _vm->_dataIO->openAsStream(handle, true);

            if (which == kVideoTypeIMD) {
                  _video = new Imd();
            } else if (which == kVideoTypeVMD) {
                  _video = new Vmd();
            } else {
                  warning("Couldn't open video \"%s\": Invalid video Type", fileName);
                  closeVideo();
                  return false;
            }

            if (!_video->load(*_stream)) {
                  warning("While loading video \"%s\"", fileName);
                  closeVideo();
                  return false;
            }

            strcpy(_curFile, fileName);

            if (!(flags & kFlagNoVideo)) {
                  _backSurf = ((flags & kFlagFrontSurface) == 0);
                  SurfaceDesc::Ptr surf = _vm->_draw->_spritesArray[_backSurf ? 21 : 20];
                  _video->setVideoMemory(surf->getVidMem(), surf->getWidth(), surf->getHeight());
            } else
                  _video->setVideoMemory();

            _video->enableSound(*_vm->_mixer);
      }

      if (!_video)
            return false;

      _video->setXY(x, y);
      WRITE_VAR(7, _video->getFramesCount());

      return true;
}

void VideoPlayer::play(int16 startFrame, int16 lastFrame, int16 breakKey,
            uint16 palCmd, int16 palStart, int16 palEnd,
            int16 palFrame, int16 endFrame, bool fade, int16 reverseTo) {

      if (!_video)
            return;

      breakKey = 27;
      if (startFrame < 0)
            startFrame = _video->getCurrentFrame();
      if (lastFrame < 0)
            lastFrame = _video->getFramesCount() - 1;
      if (palFrame < 0)
            palFrame = startFrame;
      if (endFrame < 0)
            endFrame = lastFrame;
      palCmd &= 0x3F;

      if (_video->getCurrentFrame() != startFrame) {
            if (_video->getFeatures() & CoktelVideo::kFeaturesSound)
                  startFrame = _video->getCurrentFrame();
            else
                  _video->seekFrame(startFrame);
      }

      _vm->_draw->_showCursor = 0;
      _vm->_util->setFrameRate(12);

      if (fade)
            _vm->_palAnim->fade(0, -2, 0);

      while (startFrame <= lastFrame) {
            if (doPlay(startFrame, breakKey, palCmd, palStart, palEnd, palFrame, endFrame))
                  break;

            if (fade) {
                  _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
                  fade = false;
            }

            _video->waitEndFrame();
            startFrame++;
      }

      if (reverseTo >= 0) {
            int16 toFrame = _video->getFramesCount() - reverseTo;
            for (int i = _video->getCurrentFrame(); i >= toFrame; i--) {
                  _video->seekFrame(i, SEEK_SET, true);
                  if (doPlay(i, breakKey, 0, 0, 0, 0, 0)) {
                        _vm->_palAnim->fade(0, -2, 0);
                        memset((char *) _vm->_draw->_vgaPalette, 0, 768);
                  }
                  _video->waitEndFrame();
            }
      }
}

int16 VideoPlayer::getFramesCount() const {
      if (!_video)
            return 0;

      return _video->getFramesCount();
}

int16 VideoPlayer::getCurrentFrame() const {
      if (!_video)
            return 0;

      return _video->getCurrentFrame();
}

bool VideoPlayer::doPlay(int16 frame, int16 breakKey,
            uint16 palCmd, int16 palStart, int16 palEnd,
            int16 palFrame, int16 endFrame) {

      bool modifiedPal = false;

      if ((frame == palFrame) || ((frame == endFrame) && (palCmd == 8))) {
            modifiedPal = true;
            _vm->_draw->_applyPal = true;

            if (palCmd >= 4)
                  copyPalette(palStart, palEnd);
      }

      if (modifiedPal && (palCmd == 8) && !_backSurf)
            _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);


      CoktelVideo::State state = _video->nextFrame();
      WRITE_VAR(11, frame);


      if (modifiedPal && (palCmd == 16)) {
            if (_backSurf)
                  _vm->_draw->forceBlit();
            _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);
            _vm->_draw->_noInvalidated = true;
      }

      if (state.flags & CoktelVideo::kStatePalette) {
            copyPalette(palStart, palEnd);

            if (!_backSurf)
                  _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);
            else
                  _vm->_draw->_applyPal = true;
      }

      if (modifiedPal && (palCmd == 8) && _backSurf)
            _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc);


      if (_backSurf) {
            _vm->_draw->invalidateRect(state.left, state.top, state.right, state.bottom);
            _vm->_draw->blitInvalidated();
      }
      _vm->_video->retrace();


      if (modifiedPal && ((palCmd == 2) || (palCmd == 4)))
            _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0);


      _vm->_util->processInput();

      if (_vm->_quitRequested) {
            _video->disableSound();
            return true;
      }

      if (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) breakKey) {
                  _video->disableSound();
                  return true;
            }
      }

      return false;
}

void VideoPlayer::copyPalette(int16 palStart, int16 palEnd) {
      if ((palStart == -1) || (palEnd == -1))
            memcpy((char *) _vm->_global->_pPaletteDesc->vgaPal,
                        _video->getPalette(), 768);
      else
            memcpy(((char *) (_vm->_global->_pPaletteDesc->vgaPal)) +
                        palStart * 3, _video->getPalette() + palStart * 3,
                        (palEnd - palStart + 1) * 3);
}

void VideoPlayer::writeVideoInfo(const char *video, int16 varX, int16 varY,
            int16 varFrames, int16 varWidth, int16 varHeight) {

      if (openVideo(video)) {
            WRITE_VAR_OFFSET(varX, _video->getX());
            WRITE_VAR_OFFSET(varY, _video->getY());
            WRITE_VAR_OFFSET(varFrames, _video->getFramesCount());
            WRITE_VAR_OFFSET(varWidth, _video->getWidth());
            WRITE_VAR_OFFSET(varHeight, _video->getHeight());
            closeVideo();
      } else {
            WRITE_VAR_OFFSET(varX, -1);
            WRITE_VAR_OFFSET(varY, -1);
            WRITE_VAR_OFFSET(varFrames, -1);
            WRITE_VAR_OFFSET(varWidth, -1);
            WRITE_VAR_OFFSET(varHeight, -1);
      }
}

void VideoPlayer::closeVideo() {
      delete _video;
      delete _stream;

      _video = 0;
      _stream = 0;
      *_curFile = 0;
}

} // End of namespace Gob

Generated by  Doxygen 1.6.0   Back to index