// SPDX-License-Identifier: MIT // // EmulationStation Desktop Edition // MediaViewer.cpp // // Fullscreen game media viewer. // #include "MediaViewer.h" #include "Sound.h" #include "components/VideoFFmpegComponent.h" #include "views/ViewController.h" MediaViewer::MediaViewer() : mVideo {nullptr} , mImage {nullptr} { Window::getInstance()->setMediaViewer(this); } MediaViewer::~MediaViewer() { if (mVideo) { delete mVideo; mVideo = nullptr; } if (mImage) { delete mImage; mImage = nullptr; } } bool MediaViewer::startMediaViewer(FileData* game) { mHasVideo = false; mHasImages = false; mCurrentImageIndex = 0; mScreenshotIndex = -1; mTitleScreenIndex = -1; mGame = game; initiateViewer(); if (mHasVideo || mHasImages) return true; else return false; } void MediaViewer::stopMediaViewer() { NavigationSounds::getInstance().playThemeNavigationSound(SCROLLSOUND); ViewController::getInstance()->stopViewVideos(); if (mVideo) { delete mVideo; mVideo = nullptr; } if (mImage) { delete mImage; mImage = nullptr; } mVideoFile = ""; mImageFiles.clear(); } void MediaViewer::update(int deltaTime) { if (mVideo) mVideo->update(deltaTime); } void MediaViewer::render(const glm::mat4& /*parentTrans*/) { glm::mat4 trans {Renderer::getIdentity()}; Renderer::setMatrix(trans); // Render a black background below the game media. Renderer::drawRect(0.0f, 0.0f, Renderer::getScreenWidth(), Renderer::getScreenHeight(), 0x000000FF, 0x000000FF); if (mVideo && !mDisplayingImage) { mVideo->render(trans); #if defined(USE_OPENGL_21) Renderer::postProcessingParams videoParameters; unsigned int shaders {0}; if (Settings::getInstance()->getBool("MediaViewerVideoScanlines")) shaders = Renderer::SHADER_SCANLINES; if (Settings::getInstance()->getBool("MediaViewerVideoBlur")) { shaders |= Renderer::SHADER_BLUR_HORIZONTAL; float heightModifier {Renderer::getScreenHeightModifier()}; // clang-format off if (heightModifier < 1) videoParameters.blurPasses = 2; // Below 1080 else if (heightModifier >= 4) videoParameters.blurPasses = 12; // 8K else if (heightModifier >= 2.9) videoParameters.blurPasses = 10; // 6K else if (heightModifier >= 2.6) videoParameters.blurPasses = 8; // 5K else if (heightModifier >= 2) videoParameters.blurPasses = 5; // 4K else if (heightModifier >= 1.3) videoParameters.blurPasses = 3; // 1440 else if (heightModifier >= 1) videoParameters.blurPasses = 2; // 1080 // clang-format on } Renderer::shaderPostprocessing(shaders, videoParameters); #endif } else if (mImage && mImage->hasImage() && mImage->getSize() != glm::vec2 {}) { mImage->render(trans); #if defined(USE_OPENGL_21) if (mCurrentImageIndex == mScreenshotIndex && Settings::getInstance()->getBool("MediaViewerScreenshotScanlines")) Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); else if (mCurrentImageIndex == mTitleScreenIndex && Settings::getInstance()->getBool("MediaViewerScreenshotScanlines")) Renderer::shaderPostprocessing(Renderer::SHADER_SCANLINES); #endif // This is necessary so that the video loops if viewing an image when // the video ends. if (mVideo) mVideo->handleLooping(); } } void MediaViewer::initiateViewer() { if (mGame->getType() == PLACEHOLDER) return; findMedia(); if (!mHasVideo && !mHasImages) return; if (mHasVideo) playVideo(); else showImage(0); } void MediaViewer::findMedia() { std::string mediaFile; if ((mediaFile = mGame->getVideoPath()) != "") { mVideoFile = mediaFile; mHasVideo = true; } if (!mHasVideo && (mediaFile = mGame->getScreenshotPath()) != "") { mImageFiles.push_back(mediaFile); mScreenshotIndex = 0; } if ((mediaFile = mGame->getCoverPath()) != "") mImageFiles.push_back(mediaFile); if ((mediaFile = mGame->getBackCoverPath()) != "") mImageFiles.push_back(mediaFile); if ((mediaFile = mGame->getTitleScreenPath()) != "") { mImageFiles.push_back(mediaFile); mTitleScreenIndex = static_cast(mImageFiles.size() - 1); } if (mHasVideo && (mediaFile = mGame->getScreenshotPath()) != "") { mImageFiles.push_back(mediaFile); mScreenshotIndex = static_cast(mImageFiles.size() - 1); } if ((mediaFile = mGame->getFanArtPath()) != "") mImageFiles.push_back(mediaFile); if ((mediaFile = mGame->getMiximagePath()) != "") mImageFiles.push_back(mediaFile); if (!mImageFiles.empty()) mHasImages = true; } void MediaViewer::showNext() { if (mHasImages && mCurrentImageIndex != static_cast(mImageFiles.size()) - 1) NavigationSounds::getInstance().playThemeNavigationSound(SCROLLSOUND); bool showedVideo = false; if (mVideo && !mHasImages) { return; } else if (mVideo && !Settings::getInstance()->getBool("MediaViewerKeepVideoRunning")) { delete mVideo; mVideo = nullptr; showedVideo = true; } if (mImage) { delete mImage; mImage = nullptr; } if ((mVideo || showedVideo) && !mDisplayingImage) mCurrentImageIndex = 0; else if (static_cast(mImageFiles.size()) > mCurrentImageIndex + 1) ++mCurrentImageIndex; if (mVideo) mDisplayingImage = true; showImage(mCurrentImageIndex); } void MediaViewer::showPrevious() { if ((mHasVideo && mDisplayingImage) || (!mHasVideo && mCurrentImageIndex != 0)) NavigationSounds::getInstance().playThemeNavigationSound(SCROLLSOUND); if (mCurrentImageIndex == 0 && !mHasVideo) { return; } else if (mCurrentImageIndex == 0 && mHasVideo) { if (mImage) { delete mImage; mImage = nullptr; } mDisplayingImage = false; playVideo(); return; } if (mImage) { delete mImage; mImage = nullptr; } --mCurrentImageIndex; showImage(mCurrentImageIndex); } void MediaViewer::playVideo() { if (mVideo || mVideoFile == "") return; mDisplayingImage = false; ViewController::getInstance()->pauseViewVideos(); mVideo = new VideoFFmpegComponent; mVideo->setOrigin(0.5f, 0.5f); mVideo->setPosition(Renderer::getScreenWidth() / 2.0f, Renderer::getScreenHeight() / 2.0f); if (Settings::getInstance()->getBool("MediaViewerStretchVideos")) mVideo->setResize(Renderer::getScreenWidth(), Renderer::getScreenHeight()); else mVideo->setMaxSize(Renderer::getScreenWidth(), Renderer::getScreenHeight()); mVideo->setVideo(mVideoFile); mVideo->setMediaViewerMode(true); mVideo->startVideoPlayer(); } void MediaViewer::showImage(int index) { if (mImage) return; mDisplayingImage = true; if (!mImageFiles.empty() && static_cast(mImageFiles.size()) >= index) { mImage = new ImageComponent(false, false); mImage->setImage(mImageFiles[index]); mImage->setOrigin(0.5f, 0.5f); mImage->setPosition(Renderer::getScreenWidth() / 2.0f, Renderer::getScreenHeight() / 2.0f); mImage->setMaxSize(Renderer::getScreenWidth(), Renderer::getScreenHeight()); } }