[Scummvm-git-logs] scummvm master -> 1efcf323d0580a58f8f3f9aa93ad9781446c8988
neuromancer
noreply at scummvm.org
Thu Aug 14 19:43:51 UTC 2025
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .
Summary:
1efcf323d0 PRIVATE: initial support for subtitles in videos and audio
Commit: 1efcf323d0580a58f8f3f9aa93ad9781446c8988
https://github.com/scummvm/scummvm/commit/1efcf323d0580a58f8f3f9aa93ad9781446c8988
Author: neuromancer (gustavo.grieco at gmail.com)
Date: 2025-08-14T21:14:32+02:00
Commit Message:
PRIVATE: initial support for subtitles in videos and audio
Changed paths:
engines/private/detection.cpp
engines/private/metaengine.cpp
engines/private/private.cpp
engines/private/private.h
diff --git a/engines/private/detection.cpp b/engines/private/detection.cpp
index 850277ee017..2bcb22630f5 100644
--- a/engines/private/detection.cpp
+++ b/engines/private/detection.cpp
@@ -22,7 +22,9 @@
#include "base/plugins.h"
#include "common/translation.h"
#include "engines/advancedDetector.h"
+
#include "private/private.h"
+#include "private/detection.h"
static const DebugChannelDef debugFlagList[] = {
{Private::kPrivateDebugFunction, "functions", "Function execution debug channel"},
@@ -46,7 +48,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::EN_USA,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
- GUIO1(GUIO_NOMIDI)
+ GUIO2(GUIO_NOMIDI, GAMEOPTION_SUBTITLES)
},
{
"private-eye", // Demo from the US release v1.0.0.23
@@ -56,7 +58,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::EN_USA,
Common::kPlatformWindows,
ADGF_DEMO,
- GUIO1(GUIO_NOMIDI)
+ GUIO2(GUIO_NOMIDI, GAMEOPTION_SUBTITLES)
},
{
"private-eye", // EU release (UK)
@@ -66,7 +68,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::EN_GRB,
Common::kPlatformWindows,
ADGF_NO_FLAGS,
- GUIO1(GUIO_NOMIDI)
+ GUIO2(GUIO_NOMIDI, GAMEOPTION_SUBTITLES)
},
{
"private-eye", // Demo from the EU release
@@ -76,7 +78,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::EN_GRB,
Common::kPlatformWindows,
ADGF_DEMO,
- GUIO1(GUIO_NOMIDI)
+ GUIO2(GUIO_NOMIDI, GAMEOPTION_SUBTITLES)
},
{
"private-eye", // Demo from PCGamer Disc 2.6 JULY 1996 v1.0.0.12
@@ -86,7 +88,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::EN_USA,
Common::kPlatformWindows,
ADGF_DEMO,
- GUIO1(GUIO_NOMIDI)
+ GUIO2(GUIO_NOMIDI, GAMEOPTION_SUBTITLES)
},
{
"private-eye", // Another demo
@@ -96,7 +98,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::EN_USA,
Common::kPlatformWindows,
ADGF_DEMO,
- GUIO1(GUIO_NOMIDI)
+ GUIO2(GUIO_NOMIDI, GAMEOPTION_SUBTITLES)
},
{
"private-eye", // EU release (ES)
@@ -196,7 +198,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::EN_USA,
Common::kPlatformMacintosh,
ADGF_NO_FLAGS,
- GUIO1(GUIO_NOMIDI)
+ GUIO2(GUIO_NOMIDI, GAMEOPTION_SUBTITLES)
},
{
"private-eye", // MacOS release (US) uninstalled
@@ -224,7 +226,7 @@ static const ADGameDescription gameDescriptions[] = {
Common::EN_USA,
Common::kPlatformMacintosh,
ADGF_DEMO,
- GUIO1(GUIO_NOMIDI)
+ GUIO2(GUIO_NOMIDI, GAMEOPTION_SUBTITLES)
},
{
"private-eye", // MacOS demo (US) uninstalled
diff --git a/engines/private/metaengine.cpp b/engines/private/metaengine.cpp
index f7b93438c0f..26d642953e5 100644
--- a/engines/private/metaengine.cpp
+++ b/engines/private/metaengine.cpp
@@ -21,8 +21,25 @@
#include "engines/advancedDetector.h"
#include "graphics/scaler.h"
+#include "common/translation.h"
#include "private/private.h"
+#include "private/detection.h"
+
+static const ADExtraGuiOptionsMap optionsList[] = {
+ {
+ GAMEOPTION_SUBTITLES,
+ {
+ _s("Display subtitles"),
+ _s("Use subtitles."),
+ "subtitles",
+ true,
+ 0,
+ 0
+ }
+ },
+ AD_EXTRA_GUI_OPTIONS_TERMINATOR
+};
class PrivateMetaEngine : public AdvancedMetaEngine<ADGameDescription> {
public:
@@ -30,6 +47,10 @@ public:
return "private";
}
+ const ADExtraGuiOptionsMap *getAdvancedExtraGuiOptions() const override {
+ return optionsList;
+ }
+
Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const override;
void getSavegameThumbnail(Graphics::Surface &thumb) override;
};
@@ -40,7 +61,7 @@ Common::Error PrivateMetaEngine::createInstance(OSystem *syst, Engine **engine,
}
void PrivateMetaEngine::getSavegameThumbnail(Graphics::Surface &thumb) {
- byte *palette;
+ byte *palette;
Graphics::Surface *vs = Private::g_private->decodeImage(Private::g_private->_nextVS, &palette);
::createThumbnail(&thumb, (const uint8 *)vs->getPixels(), vs->w, vs->h, palette);
vs->free();
diff --git a/engines/private/private.cpp b/engines/private/private.cpp
index 4afb7885e2a..ffd4e99c227 100644
--- a/engines/private/private.cpp
+++ b/engines/private/private.cpp
@@ -33,6 +33,7 @@
#include "common/system.h"
#include "common/timer.h"
#include "common/macresman.h"
+#include "common/language.h"
#include "common/compression/stuffit.h"
#include "graphics/paletteman.h"
#include "engines/util.h"
@@ -51,7 +52,7 @@ extern int parse(const char *);
PrivateEngine::PrivateEngine(OSystem *syst, const ADGameDescription *gd)
: Engine(syst), _gameDescription(gd), _image(nullptr), _videoDecoder(nullptr),
_compositeSurface(nullptr), _transparentColor(0), _frameImage(nullptr),
- _framePalette(nullptr), _maxNumberClicks(0), _sirenWarning(0),
+ _framePalette(nullptr), _maxNumberClicks(0), _sirenWarning(0), _subtitles(nullptr),
_screenW(640), _screenH(480) {
_rnd = new Common::RandomSource("private");
@@ -199,6 +200,15 @@ Common::SeekableReadStream *PrivateEngine::loadAssets() {
Common::Error PrivateEngine::run() {
+ // Only enable if subtitles are available
+ bool useSubtitles = false;
+ if (!Common::parseBool(ConfMan.get("subtitles"), useSubtitles))
+ error("Failed to parse bool from cheats options");
+
+ if (useSubtitles) {
+ g_system->showOverlay(false);
+ }
+
_language = Common::parseLanguage(ConfMan.get("language"));
_platform = Common::parsePlatform(ConfMan.get("platform"));
@@ -372,6 +382,8 @@ Common::Error PrivateEngine::run() {
_videoDecoder->close();
delete _videoDecoder;
_videoDecoder = nullptr;
+ delete _subtitles;
+ _subtitles = nullptr;
_currentMovie = "";
} else if (_videoDecoder->needsUpdate()) {
drawScreen();
@@ -395,6 +407,14 @@ Common::Error PrivateEngine::run() {
g_system->updateScreen();
g_system->delayMillis(10);
+ if (_subtitles) {
+ if (_mixer->isSoundHandleActive(_fgSoundHandle)) {
+ _subtitles->drawSubtitle(_mixer->getElapsedTime(_fgSoundHandle).msecs(), false);
+ } else {
+ delete _subtitles;
+ _subtitles = nullptr;
+ }
+ }
}
return Common::kNoError;
}
@@ -773,7 +793,7 @@ bool PrivateEngine::selectLocation(const Common::Point &mousePos) {
if (_locationMasks.size() == 0) {
return false;
}
-
+
uint i = 0;
uint totalLocations = 0;
for (auto &it : maps.locationList) {
@@ -795,7 +815,7 @@ bool PrivateEngine::selectLocation(const Common::Point &mousePos) {
if (!diaryPageSet) {
return true;
}
-
+
_nextSetting = _locationMasks[i].nextSetting;
return true;
@@ -912,7 +932,7 @@ void PrivateEngine::addMemory(const Common::String &path) {
}
diaryPage.memories.push_back(memory);
-
+
for (int i = _diaryPages.size() - 1; i >= 0; i--) {
if (_diaryPages[i].locationID < diaryPage.locationID) {
_diaryPages.insert_at(i + 1, diaryPage);
@@ -1448,12 +1468,41 @@ void PrivateEngine::playSound(const Common::String &name, uint loops, bool stopO
}
_mixer->playStream(Audio::Mixer::kSFXSoundType, sh, stream, -1, Audio::Mixer::kMaxChannelVolume);
+ loadSubtitles(path);
}
bool PrivateEngine::isSoundActive() {
return _mixer->isSoundIDActive(-1);
}
+void PrivateEngine::loadSubtitles(const Common::Path &path) {
+ debugC(1, kPrivateDebugFunction, "%s(%s)", __FUNCTION__, path.toString().c_str());
+ Common::String subPathStr = path.toString() + ".srt";
+ subPathStr.toLowercase();
+ subPathStr.replace('/', '_');
+ Common::String language(Common::getLanguageCode(_language));
+ if (language == "us")
+ language = "en";
+
+ Common::Path subPath = "subtitles";
+ subPath = subPath.appendComponent(language);
+ subPath = subPath.appendComponent(subPathStr);
+ debugC(1, kPrivateDebugFunction, "Loading subtitles from %s", subPath.toString().c_str());
+ if (Common::File::exists(subPath)) {
+ _subtitles = new Video::Subtitles();
+ _subtitles->loadSRTFile(subPath);
+ g_system->showOverlay(false);
+ int16 h = g_system->getOverlayHeight();
+
+ _subtitles->setBBox(Common::Rect(20, h - 120, g_system->getOverlayWidth() - 20, h - 20));
+ _subtitles->setColor(0xff, 0xff, 0xff);
+ _subtitles->setFont("LiberationSans-Regular.ttf", 50);
+
+ } else {
+ delete _subtitles;
+ _subtitles = nullptr;
+ }
+}
void PrivateEngine::playVideo(const Common::String &name) {
debugC(1, kPrivateDebugFunction, "%s(%s)", __FUNCTION__, name.c_str());
//stopSound(true);
@@ -1465,6 +1514,8 @@ void PrivateEngine::playVideo(const Common::String &name) {
if (!_videoDecoder->loadStream(file))
error("unable to load video %s", path.toString().c_str());
+
+ loadSubtitles(path);
_videoDecoder->start();
}
@@ -1472,6 +1523,8 @@ void PrivateEngine::skipVideo() {
_videoDecoder->close();
delete _videoDecoder;
_videoDecoder = nullptr;
+ delete _subtitles;
+ _subtitles = nullptr;
_currentMovie = "";
}
@@ -1651,6 +1704,9 @@ void PrivateEngine::drawScreen() {
Graphics::Surface sa = _compositeSurface->getSubArea(w);
g_system->copyRectToScreen(sa.getPixels(), sa.pitch, _origin.x, _origin.y, sa.w, sa.h);
}
+
+ if (_subtitles && _videoDecoder && !_videoDecoder->isPaused())
+ _subtitles->drawSubtitle(_videoDecoder->getTime(), false);
g_system->updateScreen();
}
diff --git a/engines/private/private.h b/engines/private/private.h
index 9bf86674e13..599215b4875 100644
--- a/engines/private/private.h
+++ b/engines/private/private.h
@@ -29,6 +29,7 @@
#include "graphics/managed_surface.h"
#include "graphics/wincursor.h"
#include "video/smk_decoder.h"
+#include "video/subtitles.h"
#include "private/grammar.h"
@@ -218,6 +219,9 @@ public:
void playVideo(const Common::String &);
void skipVideo();
+ void loadSubtitles(const Common::Path &path);
+ Video::Subtitles *_subtitles;
+
Graphics::Surface *decodeImage(const Common::String &file, byte **palette);
//byte *decodePalette(const Common::String &name);
void remapImage(uint16 ncolors, const Graphics::Surface *oldImage, const byte *oldPalette, Graphics::Surface *newImage, const byte *currentPalette);
More information about the Scummvm-git-logs
mailing list