Common::String VideoPlayer::getFileName(int slot) const { const Video *video = getVideoBySlot(slot); if (!video) return ""; return video->fileName; }
const Common::List<Common::Rect> *VideoPlayer::getDirtyRects(int slot) const { const Video *video = getVideoBySlot(slot); if (!video) return 0; return &video->decoder->getDirtyRects(); }
uint16 VideoPlayer::getDefaultY(int slot) const { const Video *video = getVideoBySlot(slot); if (!video) return 0; return video->decoder->getDefaultY(); }
Common::SeekableReadStream *VideoPlayer::getEmbeddedFile(const Common::String &fileName, int slot) { const Video *video = getVideoBySlot(slot); if (!video) return 0; return video->decoder->getEmbeddedFile(fileName); }
bool VideoPlayer::hasEmbeddedFile(const Common::String &fileName, int slot) const { const Video *video = getVideoBySlot(slot); if (!video) return false; return video->decoder->hasEmbeddedFile(fileName); }
int32 VideoPlayer::getSubtitleIndex(int slot) const { const Video *video = getVideoBySlot(slot); if (!video) return -1; return video->decoder->getSubtitleIndex(); }
void VideoPlayer::finishVideoSound(int slot) { Video *video = getVideoBySlot(slot); if (!video || !video->decoder) return; video->decoder->finishSound(); }
void VideoPlayer::pauseVideo(int slot, bool pause) { Video *video = getVideoBySlot(slot); if (!video || !video->decoder) return; video->decoder->pauseVideo(pause); }
uint32 VideoPlayer::getCurrentFrame(int slot) const { const Video *video = getVideoBySlot(slot); if (!video) return 0; return video->decoder->getCurFrame(); }
bool VideoPlayer::reopenVideo(int slot) { Video *video = getVideoBySlot(slot); if (!video) return true; return reopenVideo(*video); }
bool VideoPlayer::closeVideo(int slot) { Video *video = getVideoBySlot(slot); if (!video) return false; video->close(); return true; }
void VideoPlayer::waitSoundEnd(int slot) { Video *video = getVideoBySlot(slot); if (!video || !video->decoder) return; video->decoder->finishSound(); while(video->decoder->isSoundPlaying()) _vm->_util->longDelay(1); }
void VideoPlayer::closeLiveSound() { for (int i = 1; i < kVideoSlotCount; i++) { Video *video = getVideoBySlot(i); if (!video) continue; if (video->live) closeVideo(i); } }
void VideoPlayer::waitEndFrame(int slot, bool onlySound) { Video *video = getVideoBySlot(slot); if (!video) return; if (!onlySound || video->decoder->hasSound()) { uint32 waitTime = video->decoder->getTimeToNextFrame(); if (!video->decoder->hasSound()) waitTime = video->decoder->getStaticTimeToNextFrame(); _vm->_util->delay(waitTime); } }
bool VideoPlayer::copyFrame(int slot, Surface &dest, uint16 left, uint16 top, uint16 width, uint16 height, uint16 x, uint16 y, int32 transp) const { const Video *video = getVideoBySlot(slot); if (!video) return false; const Graphics::Surface *surface = video->decoder->getSurface(); if (!surface) return false; Surface src(surface->w, surface->h, surface->bytesPerPixel, (byte *)surface->pixels); dest.blit(src, left, top, left + width - 1, top + height - 1, x, y, transp); return true; }
bool VideoPlayer::copyFrame(int slot, Surface &dest, uint16 left, uint16 top, uint16 width, uint16 height, uint16 x, uint16 y, int32 transp) const { const Video *video = getVideoBySlot(slot); if (!video) return false; const Graphics::Surface *surface = video->decoder->getSurface(); if (!surface) return false; // FIXME? This currently casts away const from the pixel data. However, it // is only used read-only in this case (as far as I can tell). Not casting // the const qualifier away will lead to an additional allocation and copy // of the frame data which is undesirable. Surface src(surface->w, surface->h, surface->format.bytesPerPixel, (byte *)const_cast<void *>(surface->getPixels())); dest.blit(src, left, top, left + width - 1, top + height - 1, x, y, transp); return true; }
void VideoPlayer::updateLive(int slot, bool force) { Video *video = getVideoBySlot(slot); if (!video || !video->live) return; if (video->properties.startFrame >= (int32)(video->decoder->getFrameCount() - 1)) { // Video ended if (!video->properties.loop) { if (!(video->properties.flags & kFlagNoVideo)) WRITE_VAR_OFFSET(212, (uint32)-1); _vm->_vidPlayer->closeVideo(slot); return; } else { video->decoder->seek(0, SEEK_SET, true); video->properties.startFrame = -1; } } if (video->properties.startFrame == video->properties.lastFrame) // Current video sequence ended return; if (!force && (video->decoder->getTimeToNextFrame() > 0)) return; if (!(video->properties.flags & kFlagNoVideo)) WRITE_VAR_OFFSET(212, video->properties.startFrame + 1); bool backwards = video->properties.startFrame > video->properties.lastFrame; playFrame(slot, video->properties); video->properties.startFrame += backwards ? -1 : 1; if (video->properties.fade) { _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0); video->properties.fade = false; } }
bool VideoPlayer::play(int slot, Properties &properties) { Video *video = getVideoBySlot(slot); if (!video) return false; bool primary = slot == 0; if (properties.startFrame < 0) properties.startFrame = video->decoder->getCurFrame() + 1; if (properties.lastFrame < 0) properties.lastFrame = video->decoder->getFrameCount() - 1; if (properties.endFrame < 0) properties.endFrame = properties.lastFrame; if (properties.palFrame < 0) properties.palFrame = properties.startFrame; properties.startFrame--; properties.endFrame--; properties.palFrame--; 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; if (properties.noBlock) { properties.waitEndFrame = false; video->live = true; video->properties = properties; updateLive(slot, true); return true; } if ((_vm->getGameType() != kGameTypeUrban) && (_vm->getGameType() != kGameTypeBambou)) // NOTE: For testing (and comfort?) purposes, we enable aborting of all videos. // Except for Urban Runner and Bambou, where it leads to glitches properties.breakKey = kShortKeyEscape; while ((properties.startFrame != properties.lastFrame) && (properties.startFrame < (int32)(video->decoder->getFrameCount() - 1))) { playFrame(slot, properties); if (properties.canceled) break; properties.startFrame += backwards ? -1 : 1; evalBgShading(*video); if (primary && properties.fade) { _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0); properties.fade = false; } if (!_noCursorSwitch && properties.waitEndFrame) waitEndFrame(slot); } evalBgShading(*video); return true; }
bool VideoPlayer::isPlayingLive() const { const Video *video = getVideoBySlot(0); return video && video->live; }
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) { if (properties.startFrame != -1) { // Seek into the middle of the video if (video->decoder->hasSound()) { // But there's sound if (properties.forceSeek) { // And we force seeking => Seek video->decoder->disableSound(); video->decoder->seek(properties.startFrame + 1, SEEK_SET, true); } } else // No sound => We can safely seek video->decoder->seek(properties.startFrame + 1, SEEK_SET, true); } else { // Seek to the start => We can safely seek video->decoder->disableSound(); video->decoder->seek(0, SEEK_SET, true); video->decoder->enableSound(); } } if (video->decoder->getCurFrame() > properties.startFrame) // If the video is already beyond the wanted frame, skip return true; 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, properties.palStart, properties.palEnd); } if (modifiedPal && (properties.palCmd == 8) && (video->surface != _vm->_draw->_backSurface)) _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); if (_needBlit) _vm->_draw->forceBlit(); } const Graphics::Surface *surface = video->decoder->decodeNextFrame(); WRITE_VAR(11, video->decoder->getCurFrame()); uint32 ignoreBorder = 0; if (_woodruffCohCottWorkaround && (properties.startFrame == 31)) { // WORKAROUND: This frame mistakenly masks Coh Cott, making her vanish // To prevent that, we'll never draw that part ignoreBorder = 50; } if (surface && primary) { // Post-decoding palette and blitting, only for primary videos if (_needBlit) _vm->_draw->forceBlit(true); if (modifiedPal && (properties.palCmd == 16)) { if (video->surface == _vm->_draw->_backSurface) _vm->_draw->forceBlit(); _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0); _vm->_draw->_noInvalidated = true; _vm->_video->dirtyRectsAll(); } if (video->decoder->hasPalette() && (properties.palCmd > 1)) { copyPalette(*video, properties.palStart, properties.palEnd); if (video->surface != _vm->_draw->_backSurface) _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); else _vm->_draw->_applyPal = true; } const Common::List<Common::Rect> &dirtyRects = video->decoder->getDirtyRects(); if (modifiedPal && (properties.palCmd == 8) && (video->surface == _vm->_draw->_backSurface)) _vm->_video->setFullPalette(_vm->_global->_pPaletteDesc); if (video->surface == _vm->_draw->_backSurface) { for (Common::List<Common::Rect>::const_iterator rect = dirtyRects.begin(); rect != dirtyRects.end(); ++rect) _vm->_draw->invalidateRect(rect->left + ignoreBorder, rect->top, rect->right - 1, rect->bottom - 1); if (!video->live) _vm->_draw->blitInvalidated(); } else if (video->surface == _vm->_draw->_frontSurface) { for (Common::List<Common::Rect>::const_iterator rect = dirtyRects.begin(); rect != dirtyRects.end(); ++rect) _vm->_video->dirtyRectsAdd(rect->left + ignoreBorder, rect->top, rect->right - 1, rect->bottom - 1); } if (!video->live && ((video->decoder->getCurFrame() - 1) == properties.startFrame)) // Only retrace if we're playing the frame we actually want to play _vm->_video->retrace(); int32 subtitle = video->decoder->getSubtitleIndex(); if (subtitle != -1) _vm->_draw->printTotText(subtitle); if (modifiedPal && ((properties.palCmd == 2) || (properties.palCmd == 4))) _vm->_palAnim->fade(_vm->_global->_pPaletteDesc, -2, 0); } if (primary && properties.waitEndFrame) checkAbort(*video, properties); if ((video->decoder->getCurFrame() - 1) < properties.startFrame) // The video played a frame we actually didn't want, so we have to adjust properties.startFrame--; return true; }
bool VideoPlayer::slotIsOpen(int slot) const { return getVideoBySlot(slot) != 0; }