Files
NanamiAdmin 7edba3fbc0 feat: make everything threads-safe.
feat: complete `uninstall.sh` logic to make everything synced.
	feat: complete basic play logic to handle background, music,
	lyric play.
2026-08-30 15:13:28 +08:00

63 lines
2.2 KiB
C++

// lyricResolve.h
//
// Parse .lrc lyric files and play them back on a timeline in the terminal.
//
// playLyrics()/playLyricsFile() anchor their timeline at the moment they are
// called (t = 0) and print each lyric line at its timestamp. The module is
// self-contained and multibyte-safe: Japanese/Chinese UTF-8 lines are printed
// whole and only ever truncated on a character boundary.
#pragma once
#include <atomic>
#include <cstdint>
#include <string>
#include <vector>
#include "timeline.h"
namespace lr {
struct LyricLine {
int64_t timeMs = 0; // from the start of the track
std::string text; // empty => clear the display
};
struct LyricInfo {
std::vector<LyricLine> lines; // sorted ascending by timeMs (stable)
std::string title, artist, album, by;
int offsetMs = 0;
bool valid = false; // false if nothing was parsed
};
// Parse LRC text: "[mm:ss.xx]text", multiple timestamps per line, metadata
// tags ([ti:]/[ar:]/[al:]/[by:]/[offset:]) and timestamp-only lines (empty
// text, which clears the display). The [offset:] value is applied to all lines.
LyricInfo parseLrc(const std::string& text);
// Read a file and parse it. Returns a LyricInfo with valid == false on error.
LyricInfo parseLrcFile(const std::string& path);
struct LyricDisplayOptions {
int row = 0; // 1-based terminal row; 0 = auto (last terminal row)
int col = 0; // 1-based start column; 0 = column 1
int maxWidth = 0; // max display columns; 0 = terminal width - 1
bool show = true; // false => run the timeline silently (no terminal writes)
};
// Play the lyrics against `timeline` (may be null for a local clock): the
// current lyric line is displayed in real time as the timeline advances.
// Blocks until the timeline passes the last line (or `stop` is set).
// Returns 0.
int playLyrics(const LyricInfo& lyric,
const LyricDisplayOptions& opts = {},
Timeline* timeline = nullptr,
std::atomic<bool>* stop = nullptr);
int playLyricsFile(const std::string& path,
const LyricDisplayOptions& opts = {},
Timeline* timeline = nullptr,
std::atomic<bool>* stop = nullptr);
} // namespace lr