fix(mpv): auto-select subtitle and audio tracks on file open (#12)
Closes #7 mpv only turns on a subtitle that is flagged default or matches `slang`, so releases like VisionQuest (Russian dub by default, ru/ru/en subtitles, none flagged) open with subtitles off, which also disabled **Translate subtitle**. - New `TrackSelection` helpers in `qtpotato_core` with unit tests. - On file load: audio follows *Preferred languages* (Playback settings); subtitle follows *Preferred languages* (Subtitles settings), else keeps mpv's choice, else (new *Turn on a subtitle when none matches*, on by default) picks a full text subtitle in the system language, then English, then the audio language, then the default/first track. - Translate is enabled whenever the file has a text subtitle; with none or a bitmap subtitle shown it translates the best text track (English first). Verified in the real app on VisionQuest S01E01: subtitle 3 (en) is selected on open; with audio set to `en` and auto-select off, audio switches to track 7, subtitle stays off and Translate stays enabled with the English source. Reviewed-on: #12 Co-authored-by: Tri Vo Khac <git@trivk.dev>
This commit was merged in pull request #12.
This commit is contained in:
1 parent
32c686e0e3
commit
b34a01a92f
13 files changed
+437
-1
No files matched your search
@@ -19,3 +19,8 @@ ecm_add_test(playlistmodeltest.cpp ../src/playlist/playlistmodel.cpp
|
||||
LINK_LIBRARIES Qt6::Qml Qt6::Test
|
||||
)
|
||||
target_include_directories(playlistmodeltest PRIVATE ../src/playlist)
|
||||
|
||||
ecm_add_test(trackselectiontest.cpp
|
||||
TEST_NAME trackselectiontest
|
||||
LINK_LIBRARIES qtpotato_core Qt6::Test
|
||||
)
|
||||
@@ -0,0 +1,90 @@
|
||||
#include "trackselection.h"
|
||||
|
||||
#include <QTest>
|
||||
|
||||
using namespace Qt::Literals::StringLiterals;
|
||||
using TrackSelection::Track;
|
||||
|
||||
namespace
|
||||
{
|
||||
Track sub(int id, const QString &lang, const QString &codec = u"subrip"_s, bool forced = false, bool isDefault = false)
|
||||
{
|
||||
return {.id = id, .lang = lang, .codec = codec, .forced = forced, .isDefault = isDefault};
|
||||
}
|
||||
}
|
||||
|
||||
class TrackSelectionTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void matchesLanguageTags()
|
||||
{
|
||||
QVERIFY(TrackSelection::sameLanguage(u"en"_s, u"eng"_s));
|
||||
QVERIFY(TrackSelection::sameLanguage(u"en-US"_s, u"English"_s));
|
||||
QVERIFY(TrackSelection::sameLanguage(u"ger"_s, u"de"_s));
|
||||
QVERIFY(TrackSelection::sameLanguage(u"vie"_s, u"vietnamese"_s));
|
||||
QVERIFY(!TrackSelection::sameLanguage(u"en"_s, u"ru"_s));
|
||||
QVERIFY(!TrackSelection::sameLanguage(u""_s, u""_s));
|
||||
QVERIFY(!TrackSelection::sameLanguage(u"en"_s, u""_s));
|
||||
}
|
||||
|
||||
void detectsBitmapSubtitles()
|
||||
{
|
||||
QVERIFY(TrackSelection::isBitmapSubtitle(u"hdmv_pgs_subtitle"_s));
|
||||
QVERIFY(TrackSelection::isBitmapSubtitle(u"dvd_subtitle"_s));
|
||||
QVERIFY(!TrackSelection::isBitmapSubtitle(u"subrip"_s));
|
||||
QVERIFY(!TrackSelection::isBitmapSubtitle(u"ass"_s));
|
||||
QVERIFY(!TrackSelection::isBitmapSubtitle(u""_s));
|
||||
}
|
||||
|
||||
// VisionQuest release: Russian dub by default, two Russian subtitles before the
|
||||
// English one, no default subtitle, so mpv turns none on.
|
||||
void fallsBackInLanguageOrder()
|
||||
{
|
||||
const QList<Track> tracks{sub(1, u"rus"_s), sub(2, u"rus"_s), sub(3, u"eng"_s)};
|
||||
QCOMPARE(TrackSelection::pickSubtitle(tracks, {}, {u"vi"_s, u"en"_s, u"rus"_s}, 0, true), 3);
|
||||
QCOMPARE(TrackSelection::pickSubtitle(tracks, {}, {u"vi"_s, u"en"_s, u"rus"_s}, 0, false), 0);
|
||||
QCOMPARE(TrackSelection::pickSubtitle(tracks, {}, {u"ru"_s, u"en"_s}, 0, true), 1);
|
||||
QCOMPARE(TrackSelection::pickSubtitle(tracks, {}, {u"ja"_s}, 0, true), 1);
|
||||
}
|
||||
|
||||
void fallbackPrefersDefaultFullTextTracks()
|
||||
{
|
||||
const QList<Track> tracks{sub(1, u"en"_s, u"subrip"_s, true), sub(2, u"en"_s, u"hdmv_pgs_subtitle"_s), sub(3, u"en"_s), sub(4, u"fr"_s, u"subrip"_s, false, true)};
|
||||
QCOMPARE(TrackSelection::pickSubtitle(tracks, {}, {u"en"_s}, 0, true), 3);
|
||||
QCOMPARE(TrackSelection::pickSubtitle(tracks, {}, {u"ja"_s}, 0, true), 4);
|
||||
// Only forced subtitles: leave subtitles off.
|
||||
QCOMPARE(TrackSelection::pickSubtitle({sub(1, u"en"_s, u"subrip"_s, true)}, {}, {u"en"_s}, 0, true), 0);
|
||||
}
|
||||
|
||||
void preferredLanguagesWinOverMpvChoice()
|
||||
{
|
||||
const QList<Track> tracks{sub(1, u"ru"_s), sub(2, u"vi"_s), sub(3, u"en"_s)};
|
||||
QCOMPARE(TrackSelection::pickSubtitle(tracks, {u"vi"_s, u"en"_s}, {u"en"_s}, 1, true), 2);
|
||||
QCOMPARE(TrackSelection::pickSubtitle(tracks, {u"de"_s, u"English"_s}, {u"en"_s}, 1, true), 3);
|
||||
// No preferred language present: keep mpv's choice.
|
||||
QCOMPARE(TrackSelection::pickSubtitle(tracks, {u"de"_s}, {u"en"_s}, 1, true), 1);
|
||||
}
|
||||
|
||||
void picksAudioByPreference()
|
||||
{
|
||||
const QList<Track> tracks{sub(1, u"en"_s, u"aac"_s), sub(2, u"jpn"_s, u"aac"_s)};
|
||||
QCOMPARE(TrackSelection::pickAudio(tracks, {u"ja"_s}, 1), 2);
|
||||
QCOMPARE(TrackSelection::pickAudio(tracks, {u"de"_s}, 1), 1);
|
||||
QCOMPARE(TrackSelection::pickAudio(tracks, {}, 1), 1);
|
||||
}
|
||||
|
||||
void picksTextTranslationSource()
|
||||
{
|
||||
const QList<Track> tracks{sub(1, u"en"_s, u"hdmv_pgs_subtitle"_s), sub(2, u"ru"_s), sub(3, u"en"_s)};
|
||||
QCOMPARE(TrackSelection::pickTranslationSource(tracks, {u"en"_s}, 2), 2);
|
||||
QCOMPARE(TrackSelection::pickTranslationSource(tracks, {u"en"_s}, 1), 3);
|
||||
QCOMPARE(TrackSelection::pickTranslationSource(tracks, {u"en"_s}, 0), 3);
|
||||
QCOMPARE(TrackSelection::pickTranslationSource(tracks, {u"ru"_s}, 0), 2);
|
||||
QCOMPARE(TrackSelection::pickTranslationSource({sub(1, u"en"_s, u"dvd_subtitle"_s)}, {u"en"_s}, 0), 0);
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_GUILESS_MAIN(TrackSelectionTest)
|
||||
#include "trackselectiontest.moc"
|
||||
Reference in new issue
Block a user