Correctly handle lyrics that contain ] chars

This commit is contained in:
emeric
2024-11-11 21:30:01 +01:00
parent 5d94b97032
commit bdd55e5ba3
2 changed files with 22 additions and 9 deletions
+6 -9
View File
@@ -83,13 +83,14 @@ namespace lms::metadata
return true; return true;
} }
// Parse timestamps from a line and return the associated times in milliseconds // Parse timestamps from a line, update the associated times in milliseconds and return the remaining line
void extractTimestamps(std::string_view line, std::vector<std::chrono::milliseconds>& timestamps) std::string_view extractTimestamps(std::string_view line, std::vector<std::chrono::milliseconds>& timestamps)
{ {
timestamps.clear(); timestamps.clear();
static const std::regex timeTagRegex{ R"(\[(?:(\d{1,2}):)?(\d{1,2}):(\d{1,2})(?:\.(\d{1,3}))?\])" }; static const std::regex timeTagRegex{ R"(\[(?:(\d{1,2}):)?(\d{1,2}):(\d{1,2})(?:\.(\d{1,3}))?\])" };
std::cregex_iterator regexIt(line.begin(), line.end(), timeTagRegex); std::cregex_iterator regexIt(line.begin(), line.end(), timeTagRegex);
std::cregex_iterator regexEnd; std::cregex_iterator regexEnd;
std::string_view::size_type offset{};
while (regexIt != regexEnd) while (regexIt != regexEnd)
{ {
@@ -110,15 +111,12 @@ namespace lms::metadata
currentTimestamp += std::chrono::milliseconds{ fractional }; currentTimestamp += std::chrono::milliseconds{ fractional };
} }
offset = match[0].second - line.data();
timestamps.push_back(currentTimestamp); timestamps.push_back(currentTimestamp);
++regexIt; ++regexIt;
} }
}
// Extract the lyric text from a line, removing any timestamps return line.substr(offset);
std::string_view extractLyricText(std::string_view line)
{
return line.substr(line.find_last_of(']') + 1);
} }
} // namespace } // namespace
@@ -178,7 +176,7 @@ namespace lms::metadata
if (parseTag(trimmedLine, lyrics)) if (parseTag(trimmedLine, lyrics))
continue; continue;
extractTimestamps(trimmedLine, timestamps); const std::string_view lyricText{ extractTimestamps(trimmedLine, timestamps) };
// If there are timestamps, add as synchronized lyrics // If there are timestamps, add as synchronized lyrics
if (!timestamps.empty()) if (!timestamps.empty())
@@ -189,7 +187,6 @@ namespace lms::metadata
currentState = State::SynchronizedLyrics; currentState = State::SynchronizedLyrics;
applyAccumulatedLyrics(); applyAccumulatedLyrics();
std::string_view lyricText{ extractLyricText(trimmedLine) };
for (std::chrono::milliseconds timestamp : timestamps) for (std::chrono::milliseconds timestamp : timestamps)
lyrics.synchronizedLines.emplace(timestamp, lyricText); lyrics.synchronizedLines.emplace(timestamp, lyricText);
+16
View File
@@ -191,6 +191,22 @@ Some unsynchronized lyrics
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh"); EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh");
} }
TEST(Lyrics, synchronized_withTimestampsDelimiters)
{
std::istringstream is{ R"([00:03.30]Ooh, ooh ] [])" };
const Lyrics lyrics{ parseLyrics(is) };
EXPECT_TRUE(lyrics.displayArtist.empty());
EXPECT_TRUE(lyrics.displayAlbum.empty());
EXPECT_TRUE(lyrics.displayTitle.empty());
EXPECT_EQ(lyrics.offset, std::chrono::milliseconds{ 0 });
EXPECT_EQ(lyrics.unsynchronizedLines.size(), 0);
ASSERT_EQ(lyrics.synchronizedLines.size(), 1);
ASSERT_TRUE(lyrics.synchronizedLines.contains(3s + 300ms));
EXPECT_EQ(lyrics.synchronizedLines.find(3s + 300ms)->second, "Ooh, ooh ] []");
}
TEST(Lyrics, synchronized_timestampFormats) TEST(Lyrics, synchronized_timestampFormats)
{ {
std::istringstream is{ R"([00:03.30]First line std::istringstream is{ R"([00:03.30]First line