From 7140e2fe7dfb8fd6aeb39929508de52dd776a24f Mon Sep 17 00:00:00 2001 From: h465855hgg <3382198490@qq.com> Date: Fri, 17 Jul 2026 05:40:37 +0800 Subject: [PATCH 1/6] feat: add lyrics plugin --- lyrics/README.md | 86 +++++++ lyrics/krc_decode.py | 91 +++++++ lyrics/lrclib_lyric.py | 81 ++++++ lyrics/lyrics.luau | 457 +++++++++++++++++++++++++++++++++ lyrics/lyrics_service.luau | 486 ++++++++++++++++++++++++++++++++++++ lyrics/plugin.toml | 152 +++++++++++ lyrics/thumbnail.webp | Bin 0 -> 13748 bytes lyrics/translations/en.json | 85 +++++++ 8 files changed, 1438 insertions(+) create mode 100644 lyrics/README.md create mode 100644 lyrics/krc_decode.py create mode 100644 lyrics/lrclib_lyric.py create mode 100644 lyrics/lyrics.luau create mode 100644 lyrics/lyrics_service.luau create mode 100644 lyrics/plugin.toml create mode 100644 lyrics/thumbnail.webp create mode 100644 lyrics/translations/en.json diff --git a/lyrics/README.md b/lyrics/README.md new file mode 100644 index 0000000..58dd762 --- /dev/null +++ b/lyrics/README.md @@ -0,0 +1,86 @@ +# Lyrics + +Lyrics adds a synchronized status-bar lyric display with album artwork, karaoke +highlighting, animated line changes, and configurable online or local sources. + +## Plugin + +| Field | Value | +| --- | --- | +| ID | `h465855hgg/lyrics` | +| Entries | Bar widget: `lyrics`; service: `service` | + +## Requirements + +Install `playerctl`, `python3`, `curl`, and `cp` on `PATH`. The active media +player must expose MPRIS metadata for automatic track and playback detection. + +## Usage + +Enable `h465855hgg/lyrics`, then add the `lyrics` bar widget in Noctalia's bar +settings. The background `service` detects the active MPRIS player, resolves +lyrics, downloads or caches album artwork, and publishes playback state to the +widget. + +Left-click the widget to switch between lyrics and track information. Right-click +to pause or resume the active player. Paused content is dimmed and all lyric, +transition, and marquee animation stops until playback resumes. + +When synchronized lyrics are unavailable, the widget displays +`track title + artist`. Long lines pause at each end while scrolling. Intro and +instrumental gaps can show a configurable cue such as `•••••`. + +## Settings + +| Setting | Type | Default | Description | +| --- | --- | --- | --- | +| `lyrics_source` | `select` | `auto` | Selects automatic fallback, LRCLIB, public NetEase, MPRIS text, custom HTTP, or external IPC. | +| `custom_url` | `string` | empty | HTTP URL template with `{title}`, `{artist}`, `{album}`, and `{duration}` placeholders. | +| `custom_json_field` | `string` | `syncedLyrics` | Dotted field path containing an LRC string or timed-lines array in a JSON response. | +| `cue_text` | `string` | `•••••` | Characters highlighted through long intro or instrumental gaps. | +| `scroll_mode` | `select` | `auto` | Enables automatic marquee, forced marquee, or static truncation. | +| `marquee_speed` | `int` | `30` | Approximate long-line scroll speed in logical pixels per second. | +| `max_lines` | `int` | `1` | Number of lines shown on a vertical bar, from 1 to 3. | +| `gradient` | `bool` | `true` | Enables progressive per-character highlighting. | +| `animation` | `select` | `karaoke` | Chooses karaoke, cascade, wave, fade-only, or no line transition. | +| `max_chars` | `int` | `24` | Number of visible Unicode characters before marquee scrolling starts. | +| `char_width` | `int` | `9` | Estimated logical-pixel character width used for scroll timing and minimum layout width. | +| `glyph` | `glyph` | `music` | Fallback icon shown when album artwork is unavailable. | +| `show_artist` | `bool` | `true` | Includes the artist in track-information mode. | +| `hide_when_paused` | `bool` | `false` | Hides the widget instead of dimming it while paused. | +| `show_cover` | `bool` | `true` | Shows circular album artwork beside the lyrics. | + +## IPC + +External players can set `lyrics_source` to `external` and address the singleton +service with: + +```sh +noctalia msg plugin h465855hgg/lyrics:service all '' +``` + +Supported events: + +- `push-lrc`: accepts synchronized or plain LRC text. +- `push-json`: accepts JSON with a `lines` timed array or a `lyrics` LRC string. +- `push-state`: also accepts `track`, `position`, `playing`, and `cover` fields. +- `clear`: clears the currently published lyrics. + +Line timestamps and character timestamps are milliseconds. MPRIS track duration +and playback position are microseconds: + +```json +{"lines":[{"time":1200,"duration":1800,"text":"Hello","chars":[1200,1500,1800,2100,2400]}]} +``` + +## Notes + +Automatic mode requests LRCLIB first, then the public NetEase Music API. Custom +HTTP mode contacts only the configured endpoint. The plugin never reads browser +cookies or player credentials. + +The service runs `playerctl` to read and control MPRIS playback, `python3` for the +LRCLIB helper and dynamic-lyric parser, `curl` for the public NetEase API, and +`cp` to preserve temporary local cover files. Query scratch files and downloaded +cover images are written inside the plugin runtime directory. Remote code is +never downloaded or executed. diff --git a/lyrics/krc_decode.py b/lyrics/krc_decode.py new file mode 100644 index 0000000..fc2ab34 --- /dev/null +++ b/lyrics/krc_decode.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +# Decode NetEase KRC ("klyric") dynamic lyrics into per-character timings. +# Reads the klyric field (base64 of "krc1" + zlib stream) from argv[1], +# writes JSON: {"type":"krc","lines":[{"time":ms,"text":"...","chars":[ms,...]}]} +import sys, json, base64, zlib, re + +def find_zlib(buf): + for i in range(len(buf) - 1): + if buf[i] == 0x78 and buf[i + 1] in (0x01, 0x9c, 0xda): + try: + return zlib.decompress(buf[i:]) + except Exception: + continue + return None + +def decode_krc(raw): + if isinstance(raw, str) and re.search(r"^\[\d+,\d+\]", raw, re.MULTILINE): + return raw + data = None + if isinstance(raw, str): + try: + data = base64.b64decode(raw) + except Exception: + data = raw.encode("latin-1") + else: + data = raw + if data[:4] == b"krc1": + data = data[4:] + dec = find_zlib(data) + if dec is None: + return None + try: + return dec.decode("utf-8") + except Exception: + return dec.decode("utf-8", "ignore") + +LINE_RE = re.compile(r"^\[(\d+),(\d+)\](.*)$") +PREFIX_SYL_RE = re.compile(r"(?:<|\()(\d+),(\d+)(?:,\d+)?(?:>|\))([^<(]*)") +SUFFIX_SYL_RE = re.compile(r"(.*?)<(\d+),(\d+)(?:,\d+)?>") + +def parse_krc(text): + out = [] + for line in text.splitlines(): + m = LINE_RE.match(line) + if not m: + continue + start = int(m.group(1)) + dur = int(m.group(2)) + body = m.group(3) + # NetEase has shipped both `(offset,duration,0)word` and + # `word` variants of its word-synced format. + prefixed = PREFIX_SYL_RE.findall(body) if re.match(r"^[<(]\d+,", body) else [] + if prefixed: + syl = [(word, int(offset), int(duration)) + for offset, duration, word in prefixed] + else: + syl = [(word, int(offset), int(duration)) + for word, offset, duration in SUFFIX_SYL_RE.findall(body)] + if not syl and body.strip() != "": + syl = [(body, 0, dur)] + chars = [] + full = "" + for (word, so, sd) in syl: + n = len(word) + if n == 0: + continue + for j in range(n): + chars.append(start + so + (j * sd) // n) + full += word[j] + if full.strip() != "": + out.append({"time": start, "duration": dur, "text": full, "chars": chars}) + return out + +def main(): + if len(sys.argv) < 2: + print(json.dumps({"type": "none"})) + return + try: + with open(sys.argv[1], "r", encoding="utf-8") as f: + raw = f.read() + except Exception: + print(json.dumps({"type": "none"})) + return + text = decode_krc(raw) + if text is None: + print(json.dumps({"type": "none"})) + return + print(json.dumps({"type": "krc", "lines": parse_krc(text)}, ensure_ascii=False)) + +if __name__ == "__main__": + main() diff --git a/lyrics/lrclib_lyric.py b/lyrics/lrclib_lyric.py new file mode 100644 index 0000000..9c953fb --- /dev/null +++ b/lyrics/lrclib_lyric.py @@ -0,0 +1,81 @@ +#!/usr/bin/env python3 +import sys, os, json, urllib.request, urllib.parse + +LRCLIB = "https://lrclib.net/api/search" + + +def norm(s): + return "".join(ch for ch in (s or "") if ch.isalnum() or "\u4e00" <= ch <= "\u9fff").lower() + + +def http_get(url): + req = urllib.request.Request(url, headers={ + "User-Agent": "lyrics-plugin/1.0", + "Accept": "application/json", + }) + with urllib.request.urlopen(req, timeout=15) as r: + return r.read().decode("utf-8", "ignore") + + +def main(): + raw = sys.argv[1] if len(sys.argv) > 1 else "" + title, artist, album = "test", "", "" + if raw and os.path.isfile(raw): + try: + with open(raw, encoding="utf-8") as f: + lines = [l.strip() for l in f.read().splitlines()] + title = lines[0] if lines else "test" + artist = lines[1] if len(lines) > 1 else "" + album = lines[2] if len(lines) > 2 else "" + except Exception as e: + out = {"type": "none", "lines": [], "lrc": "", "diag": [f"query_file_read_err={e!r}"]} + print(json.dumps(out, ensure_ascii=False)) + return + else: + title = raw or "test" + + out = {"type": "none", "lines": [], "lrc": "", "diag": []} + try: + q = urllib.parse.urlencode({"track_name": title, "artist_name": artist or title}) + s = json.loads(http_get(LRCLIB + "?" + q)) + if not s: + out["diag"].append("lrclib: no results") + print(json.dumps(out, ensure_ascii=False)) + return + + nart = norm(artist) + nalb = norm(album) + ntitle = norm(title) + best = None + for c in s: + cn = norm(c.get("trackName", "")) + ca = norm(c.get("artistName", "")) + if ntitle and cn != ntitle and ntitle not in cn and cn not in ntitle: + continue + if nart and ca and (nart in ca or ca in nart): + best = c + break + if nalb and norm(c.get("albumName", "")) == nalb: + best = c + break + if best is None: + best = c + if best is None: + best = s[0] + + lrc = best.get("syncedLyrics") or best.get("plainLyrics") or "" + if not lrc: + out["diag"].append("lrclib: empty lyrics") + print(json.dumps(out, ensure_ascii=False)) + return + out["lrc"] = lrc + out["type"] = "lrc" + out["diag"].append(f"lrclib: {best.get('trackName')} / {best.get('artistName')} synced={bool(best.get('syncedLyrics'))}") + print(json.dumps(out, ensure_ascii=False)) + except Exception as e: + out["diag"].append(f"lrclib ERR: {e!r}") + print(json.dumps(out, ensure_ascii=False)) + + +if __name__ == "__main__": + main() diff --git a/lyrics/lyrics.luau b/lyrics/lyrics.luau new file mode 100644 index 0000000..bb9a4cd --- /dev/null +++ b/lyrics/lyrics.luau @@ -0,0 +1,457 @@ +--!nonstrict +-- Synchronized lyrics bar widget with karaoke highlighting and long-line scrolling. + +noctalia.setUpdateInterval(33) + +local glyph = noctalia.getConfig("glyph") +local showArtist = noctalia.getConfig("show_artist") +local hideWhenPaused = noctalia.getConfig("hide_when_paused") +local showCover = noctalia.getConfig("show_cover") +if showCover == nil then showCover = true end + +-- These are plugin settings, not per-widget settings. +local scrollMode = noctalia.getConfig("scroll_mode") or "auto" +local marqueeSpeed = tonumber(noctalia.getConfig("marquee_speed")) or 30 +local maxLines = tonumber(noctalia.getConfig("max_lines")) or 1 +local maxChars = tonumber(noctalia.getConfig("max_chars")) or 24 +local charWidth = tonumber(noctalia.getConfig("char_width")) or 9 +local gradientOn = noctalia.getConfig("gradient") +if gradientOn == nil then gradientOn = true end +local animation = noctalia.getConfig("animation") or "karaoke" +local cueText = noctalia.getConfig("cue_text") or "•••••" +if cueText == "" then cueText = "•••••" end + +local track = nil +local lyrics = nil +local cover = nil +local playing = false +local showMode = "auto" +local rendered = false + +local baselinePosition = 0 +local baselineClock = os.clock() +local lastClock = 0 +local displayKey = "" +local displayedLine = nil +local outgoingLine = nil +local transitionElapsed = 0 +local marqueeElapsed = 0 +local smoothProgress = 0 + +local FADE_OUT_MS = 130 +local FADE_IN_MS = 260 +local MARQUEE_HOLD = 1.1 +local BLEND_MS = 350 +local INTERLUDE_GAP_MS = 7000 +local INTRO_MIN_MS = 6000 +local INTERLUDE_MIN_MS = 8000 + +local function clamp(value, low, high) + return math.min(high, math.max(low, value)) +end + +local function easeOutCubic(t) + local u = 1 - clamp(t, 0, 1) + return 1 - u * u * u +end + +local function toChars(text) + local chars = {} + local i = 1 + while i <= #text do + local byte = text:byte(i) + local length = 1 + if byte >= 0xF0 then length = 4 + elseif byte >= 0xE0 then length = 3 + elseif byte >= 0xC0 then length = 2 end + chars[#chars + 1] = text:sub(i, i + length - 1) + i = i + length + end + return chars +end + +local function getProgressMs() + local elapsed = playing and (os.clock() - baselineClock) * 1000 or 0 + return baselinePosition / 1000 + elapsed +end + +local function getLineInfo() + if not lyrics or #lyrics == 0 or not track then return nil end + + local position = getProgressMs() + local synced = lyrics[1].time >= 0 + if not synced then + return { key = "plain", index = 1, line = lyrics[1], progress = 0, synced = false } + end + + local firstTime = lyrics[1].time + if firstTime >= INTRO_MIN_MS and position < firstTime then + return { + key = "intro", + index = 0, + line = { text = cueText }, + progress = clamp(position / firstTime, 0, 1), + synced = true, + position = position, + cue = true, + } + end + + local index = 1 + for i = #lyrics, 1, -1 do + if lyrics[i].time <= position then + index = i + break + end + end + + local line = lyrics[index] + local startTime = line.time + local durationMs = track.duration and track.duration > 0 and track.duration / 1000 or nil + local nextLine = lyrics[index + 1] + local nextTime = nextLine and nextLine.time + or durationMs + or (startTime + 4000) + local lineEnd = nextTime + + if line.duration and line.duration > 0 then + lineEnd = math.min(nextTime, startTime + line.duration) + elseif nextTime - startTime >= INTERLUDE_GAP_MS then + -- LRC only marks line starts. Do not stretch a lyric across a long instrumental gap. + local estimatedDuration = clamp(#toChars(line.text) * 320, 3200, 6000) + lineEnd = math.min(nextTime, startTime + estimatedDuration) + end + + -- Only show an interlude between two real lyric lines. The final lyric stays + -- visible through the outro instead of turning the whole song ending into dots. + if nextLine and nextTime - lineEnd >= INTERLUDE_MIN_MS and position >= lineEnd then + return { + key = "interlude-" .. tostring(index), + index = index, + line = { text = cueText }, + progress = clamp((position - lineEnd) / (nextTime - lineEnd), 0, 1), + synced = true, + position = position, + cue = true, + } + end + + local progress = lineEnd > startTime and clamp((position - startTime) / (lineEnd - startTime), 0, 1) or 1 + + return { + key = "line-" .. tostring(index), + index = index, + line = line, + progress = progress, + synced = true, + position = position, + } +end + +local function getTrackLabel() + if not track then return "--" end + if not showArtist then return track.title end + if track.artist and track.artist ~= "" then + return track.artist .. " - " .. track.title + end + return track.title +end + +local function getFallbackLabel() + if not track then return "--" end + if track.artist and track.artist ~= "" then + return track.title .. " + " .. track.artist + end + return track.title +end + +local function shouldMarquee(text) + return scrollMode ~= "static" and #toChars(text) > maxChars +end + +local function getMarqueeOffset(length) + local distance = math.max(0, length - maxChars) + if distance == 0 then return 0 end + + -- The setting is pixels per second; convert it to character cells per second. + local charsPerSecond = math.max(0.5, marqueeSpeed / math.max(1, charWidth)) + local travelTime = distance / charsPerSecond + local cycle = MARQUEE_HOLD * 2 + travelTime * 2 + local phase = marqueeElapsed % cycle + + if phase < MARQUEE_HOLD then return 0 end + phase = phase - MARQUEE_HOLD + if phase < travelTime then return distance * (phase / travelTime) end + phase = phase - travelTime + if phase < MARQUEE_HOLD then return distance end + phase = phase - MARQUEE_HOLD + return distance * (1 - phase / travelTime) +end + +local function karaokeColor(charTime, charProgress, position, useGradient) + if not playing then return "on_surface_variant" end + local active = noctalia.isDarkMode() and "primary" or "on_surface" + local inactive = "on_surface_variant" + if charTime and position then + if not useGradient then + return position >= charTime and active or inactive + end + if position >= charTime then return active end + local distance = charTime - position + if distance >= BLEND_MS then return inactive end + local alpha = 1 - distance / BLEND_MS + if alpha <= 0.5 then return inactive end + return active .. "/" .. string.format("%.2f", math.max(0.72, alpha)) + end + + if not useGradient then + return smoothProgress >= charProgress and active or inactive + end + local distance = charProgress - smoothProgress + if distance <= 0 then return active end + if distance >= 0.16 then return inactive end + local alpha = 1 - distance / 0.16 + if alpha <= 0.5 then return inactive end + return active .. "/" .. string.format("%.2f", math.max(0.72, alpha)) +end + +local function buildLineRow(line, opts) + opts = opts or {} + local text = type(line) == "table" and line.text or line + local times = type(line) == "table" and line.chars or nil + local chars = toChars(text or "") + if #chars == 0 then chars = { " " } end + + local exactOffset = opts.marquee and getMarqueeOffset(#chars) or 0 + local offset = math.floor(exactOffset) + local fraction = exactOffset - offset + local first = offset + 1 + local last = math.min(#chars, first + maxChars) + local labels = {} + + for sourceIndex = first, last do + local active = playing and (noctalia.isDarkMode() and "primary" or "on_surface") or "on_surface_variant" + local color = opts.dim and "on_surface_variant" or active + if not opts.solid and not opts.dim then + local progress = #chars > 1 and (sourceIndex - 1) / (#chars - 1) or 0 + color = karaokeColor(times and times[sourceIndex], progress, opts.position, opts.useGradient) + end + + -- Soft viewport edges make cell-by-cell marquee movement less abrupt. + local alpha = 1 + local edgeAlpha = noctalia.isDarkMode() and 0.5 or 0.72 + if opts.marquee and offset > 0 and sourceIndex == first then alpha = edgeAlpha end + if opts.marquee and last < #chars and sourceIndex == last then alpha = edgeAlpha end + if opts.cascade then + local charProgress = (sourceIndex - first) / math.max(1, last - first) + local cascadeProgress = clamp((transitionElapsed - FADE_OUT_MS) / 420, 0, 1) + alpha = alpha * clamp((cascadeProgress - charProgress * 0.45) * 2.4, 0.08, 1) + end + if opts.wave then + local waveProgress = clamp((transitionElapsed - FADE_OUT_MS) / 650, 0, 1) + local wave = 0.55 + 0.45 * math.sin(waveProgress * math.pi * 2 - sourceIndex * 0.78) + alpha = alpha * (wave * (1 - waveProgress) + waveProgress) + end + + -- Bar labels elide glyphs when constrained below their natural width, so + -- animate the viewport edges with opacity without clipping CJK characters. + if opts.marquee and fraction > 0 then + if sourceIndex == first then + alpha = alpha * (1 - fraction) + elseif sourceIndex == first + maxChars then + alpha = alpha * fraction + end + elseif sourceIndex == first + maxChars then + alpha = 0 + end + + labels[#labels + 1] = ui.label({ + key = "char-" .. tostring(sourceIndex), + text = chars[sourceIndex], + color = color, + opacity = alpha, + maxLines = 1, + }) + end + + if opts.marquee then + while #labels < maxChars + 1 do + labels[#labels + 1] = ui.label({ text = " ", opacity = 0, maxLines = 1 }) + end + end + + return ui.row({ + key = opts.key or "line", + gap = 0, + align = "center", + minWidth = maxChars * charWidth, + opacity = opts.opacity or 1, + }, labels) +end + +local function currentTransitionLine(info) + if animation == "none" or transitionElapsed >= FADE_OUT_MS then + local opacity = animation == "none" and 1 + or easeOutCubic((transitionElapsed - FADE_OUT_MS) / FADE_IN_MS) + return info and info.line or nil, opacity + end + return outgoingLine, 1 - easeOutCubic(transitionElapsed / FADE_OUT_MS) +end + +local function render() + if hideWhenPaused and not playing then + barWidget.setVisible(false) + return + end + barWidget.setVisible(true) + + local vertical = barWidget.isVertical() + local useGradient = (animation == "karaoke" or animation == "cascade" or animation == "wave") and gradientOn + local position = getProgressMs() + local prefix = {} + local coverPath = showCover and cover and cover ~= "" and noctalia.fileExists(cover) and cover or nil + if coverPath then + prefix[#prefix + 1] = ui.image({ path = coverPath, width = 18, height = 18, radius = 9, fit = "cover" }) + else + prefix[#prefix + 1] = ui.glyph({ + name = glyph, + size = 14, + color = playing and (noctalia.isDarkMode() and "primary" or "on_surface") or "on_surface_variant", + }) + end + + local lineNodes = {} + if showMode == "track" then + local label = getTrackLabel() + lineNodes[1] = buildLineRow(label, { + key = "track", + marquee = shouldMarquee(label), + solid = true, + }) + else + local info = getLineInfo() + if info then + local shownLine, opacity = currentTransitionLine(info) + if shownLine then + lineNodes[#lineNodes + 1] = buildLineRow(shownLine, { + key = "current-" .. tostring(info.index), + marquee = shownLine == info.line and shouldMarquee(shownLine.text), + position = position, + useGradient = shownLine == info.line and info.synced and useGradient, + solid = not info.synced or (animation ~= "karaoke" and animation ~= "cascade" and animation ~= "wave"), + cascade = shownLine == info.line and animation == "cascade", + wave = shownLine == info.line and animation == "wave", + opacity = opacity, + }) + end + + if vertical and maxLines > 1 and shownLine == info.line then + for i = 1, maxLines - 1 do + local nextLine = lyrics[info.index + i] + if not nextLine then break end + lineNodes[#lineNodes + 1] = buildLineRow(nextLine, { + key = "next-" .. tostring(info.index + i), + dim = true, + opacity = math.max(0.25, 0.58 - (i - 1) * 0.16), + }) + end + end + else + local label = getFallbackLabel() + lineNodes[1] = buildLineRow(label, { + key = "fallback", + marquee = shouldMarquee(label), + solid = true, + }) + end + end + + if vertical then + barWidget.render(ui.column({ gap = 3, align = "start", opacity = playing and 1 or 0.58 }, { + ui.row({ gap = 6, align = "center" }, prefix), + ui.column({ gap = 2, align = "start" }, lineNodes), + })) + else + local children = {} + for _, node in ipairs(prefix) do children[#children + 1] = node end + children[#children + 1] = lineNodes[1] + barWidget.render(ui.row({ gap = 6, align = "center", opacity = playing and 1 or 0.58 }, children)) + end + + barWidget.setTooltip(getTrackLabel()) + rendered = true +end + +function onClick() + showMode = showMode == "auto" and "track" or "auto" + marqueeElapsed = 0 + if rendered then render() end +end + +function onRightClick() + noctalia.runAsync("playerctl play-pause", function(result) + if result.exitCode == 0 then + local wasPlaying = playing + if wasPlaying then baselinePosition = getProgressMs() * 1000 end + playing = not wasPlaying + noctalia.state.set("playing", playing) + baselineClock = os.clock() + render() + end + end) +end + +function update() + local now = os.clock() + local delta = lastClock > 0 and now - lastClock or 0 + lastClock = now + + track = noctalia.state.get("track") + lyrics = noctalia.state.get("lyrics") + cover = noctalia.state.get("cover") + playing = noctalia.state.get("playing") == true + + local info = getLineInfo() + local nextKey = info and info.key or "fallback" + if nextKey ~= displayKey then + outgoingLine = displayedLine + displayKey = nextKey + transitionElapsed = animation == "none" and FADE_OUT_MS + FADE_IN_MS or 0 + marqueeElapsed = 0 + smoothProgress = info and info.progress or 0 + else + local target = info and info.progress or 0 + smoothProgress = smoothProgress + (target - smoothProgress) * math.min(1, delta * 8) + end + displayedLine = info and info.line or nil + + if playing then + transitionElapsed = transitionElapsed + delta * 1000 + local text = showMode == "track" and getTrackLabel() or (info and info.line.text or "") + if shouldMarquee(text) then marqueeElapsed = marqueeElapsed + delta end + end + + render() +end + +noctalia.state.watch("position", function(value) + baselinePosition = tonumber(value) or 0 + baselineClock = os.clock() +end) + +noctalia.state.watch("lyrics", function(value) + lyrics = value + displayKey = "" + displayedLine = nil + outgoingLine = nil + marqueeElapsed = 0 +end) + +noctalia.state.watch("playing", function(value) + -- Preserve the interpolated position when pausing between service polls. + if playing and value ~= true then + baselinePosition = getProgressMs() * 1000 + end + playing = value == true + baselineClock = os.clock() +end) diff --git a/lyrics/lyrics_service.luau b/lyrics/lyrics_service.luau new file mode 100644 index 0000000..3368540 --- /dev/null +++ b/lyrics/lyrics_service.luau @@ -0,0 +1,486 @@ +--!nonstrict +-- Lyrics — headless service. +-- Polls MPRIS metadata via playerctl, fetches lyrics from NetEase Cloud Music +-- via /api endpoints, publishes state. No polling delay. + +noctalia.setUpdateInterval(250) + +local cache = {} +local coverCache = {} +local lastTrackKey = "" +local inFlight = nil +local coverInFlight = nil +local krcTmp = (noctalia.pluginDir() or "/tmp") .. "/.krc_cache.tmp" +local lyricsSource = noctalia.getConfig("lyrics_source") or "auto" +local customUrl = noctalia.getConfig("custom_url") or "" +local customJsonField = noctalia.getConfig("custom_json_field") or "syncedLyrics" +local currentTrack = nil +local currentEmbeddedLyrics = "" + +local function coverPathFor(track) + local safe = (track.artist .. "_" .. track.album .. "_" .. track.title):gsub("[^%w]+", "_") + return noctalia.pluginDir() .. "/cover_" .. safe .. ".jpg" +end + +local function shellQuote(value) + return "'" .. tostring(value):gsub("'", "'\\''") .. "'" +end + +local function parseLRC(lrcText) + local lines = {} + for line in lrcText:gmatch("[^\n]+") do + local mins, secs = line:match("%[(%d+):(%d+%.?%d*)%]") + if mins and secs then + local ms = math.floor(tonumber(mins) * 60000 + tonumber(secs) * 1000) + local text = line:gsub("%[%d+:%d+%.?%d*%]", ""):gsub("^%s+", ""):gsub("%s+$", "") + if text ~= "" then + local isMeta = ms < 5000 and (text:find(":") or text:find(":")) + if not isMeta then + lines[#lines + 1] = { time = ms, text = text } + end + end + end + end + if #lines == 0 then return nil end + return lines +end + +local function parsePlain(text) + local lines = {} + local seenLyric = false + for line in text:gmatch("[^\n]+") do + local trimmed = line:gsub("^%s+", ""):gsub("%s+$", "") + if trimmed ~= "" then + if seenLyric then + lines[#lines + 1] = { time = -1, text = trimmed } + elseif trimmed:find(":") or trimmed:find(":") then + -- skip metadata header line + else + seenLyric = true + lines[#lines + 1] = { time = -1, text = trimmed } + end + end + end + if #lines == 0 then return nil end + return lines +end + +local function evictCache() + local keys = {} + for k, _ in pairs(cache) do keys[#keys + 1] = k end + if #keys > 30 then + table.sort(keys) + for i = 1, #keys - 30 do cache[keys[i]] = nil end + end +end + +local function fetchLyricsNetEase(track, embeddedLyrics) + if inFlight then return end + inFlight = track + + local tk = track.title .. "|" .. track.artist .. "|" .. track.album + + local function tryFetch(query, fallback) + local searchUrl = "https://music.163.com/api/search/get?type=1&s=" .. noctalia.string.urlEncode(query) .. "&limit=5" + local cmd = 'curl -s --max-time 10 --connect-timeout 5 "' .. searchUrl .. '" -H "Referer: https://music.163.com"' + + noctalia.runAsync(cmd, function(r1) + if not inFlight then return end + if tk ~= lastTrackKey then inFlight = nil; return end + + if r1.exitCode ~= 0 or not r1.stdout or #r1.stdout == 0 then + if fallback then fallback() + else inFlight = nil; noctalia.state.set("lyrics", nil) end + return + end + + local data = noctalia.json.decode(r1.stdout) + if not data or not data.result or not data.result.songs or #data.result.songs == 0 then + if fallback then fallback() + else inFlight = nil; noctalia.state.set("lyrics", nil) end + return + end + + local function songArtist(s) + if s.artists and #s.artists > 0 then + return (s.artists[1].name or ""):lower() + end + return "" + end + + local bestMatch = nil + local trackArtist = track.artist:lower() + for _, s in ipairs(data.result.songs) do + if songArtist(s):find(trackArtist, 1, true) then + bestMatch = s + break + end + end + if not bestMatch then + bestMatch = data.result.songs[1] + end + + local songId = bestMatch.id + local lyricUrl = "https://music.163.com/api/song/lyric?id=" .. songId .. "&lv=1&kv=1&tv=-1" + local lCmd = 'curl -s --max-time 10 --connect-timeout 5 "' .. lyricUrl .. '" -H "Referer: https://music.163.com"' + + noctalia.runAsync(lCmd, function(r2) + if not inFlight then return end + if tk ~= lastTrackKey then inFlight = nil; return end + + local lyrics = nil + if r2.exitCode == 0 and r2.stdout and #r2.stdout > 0 then + local ldata = noctalia.json.decode(r2.stdout) + local klyricStr = "" + if ldata and ldata.klyric then + local k = ldata.klyric + if type(k) == "string" then + klyricStr = k + elseif type(k) == "table" then + klyricStr = (k.lyric and type(k.lyric) == "string") and k.lyric or "" + end + end + if klyricStr ~= "" then + local ok = pcall(noctalia.writeFile, krcTmp, klyricStr) + if not ok then klyricStr = "" end + end + if klyricStr ~= "" then + local py = 'python3 "' .. noctalia.pluginDir() .. '/krc_decode.py" "' .. krcTmp .. '"' + noctalia.runAsync(py, function(r3) + if not inFlight then return end + if tk ~= lastTrackKey then inFlight = nil; return end + local ok, parsed = pcall(noctalia.json.decode, r3.stdout or "") + if ok and parsed and parsed.type == "krc" and parsed.lines then + cache[tk] = parsed.lines + evictCache() + inFlight = nil + noctalia.state.set("lyrics", parsed.lines) + return + end + local lrc = (ldata.lrc and ldata.lrc.lyric) or "" + local lyr = parseLRC(lrc) + if not lyr then lyr = parsePlain(lrc) end + if lyr then + cache[tk] = lyr + evictCache() + inFlight = nil + noctalia.state.set("lyrics", lyr) + elseif fallback then + fallback() + else + inFlight = nil + noctalia.state.set("lyrics", nil) + end + end) + return + end + if ldata and ldata.lrc and ldata.lrc.lyric and ldata.lrc.lyric ~= "" then + lyrics = parseLRC(ldata.lrc.lyric) + if not lyrics then + lyrics = parsePlain(ldata.lrc.lyric) + end + end + end + + if lyrics then + cache[tk] = lyrics + evictCache() + inFlight = nil + noctalia.state.set("lyrics", lyrics) + elseif fallback then + fallback() + else + inFlight = nil + noctalia.state.set("lyrics", nil) + end + end) + end) + end + + local query = track.title .. "\n" .. track.artist .. "\n" .. (track.album or "") + local qTmp = (noctalia.pluginDir() or "/tmp") .. "/.query_cache.tmp" + noctalia.writeFile(qTmp, query) + local dir = noctalia.pluginDir() or "/tmp" + + local function applyParsed(parsed) + if parsed and parsed.type == "krc" and parsed.lines then + cache[tk] = parsed.lines + evictCache() + noctalia.state.set("lyrics", parsed.lines) + return true + end + if parsed and parsed.type == "lrc" and parsed.lrc and parsed.lrc ~= "" then + local lyr = parseLRC(parsed.lrc) + if not lyr then lyr = parsePlain(parsed.lrc) end + if lyr then + cache[tk] = lyr + evictCache() + noctalia.state.set("lyrics", lyr) + return true + end + end + return false + end + + local function runPy(script, cb) + local py = 'python3 "' .. dir .. "/" .. script .. '" "' .. qTmp .. '"' + noctalia.runAsync(py, function(r) + if not inFlight then return end + if tk ~= lastTrackKey then inFlight = nil; return end + local ok, parsed = pcall(noctalia.json.decode, r.stdout or "") + cb(ok and parsed or nil) + end) + end + + local function applyText(text) + if not text or text == "" then return false end + local parsed = parseLRC(text) + if not parsed then parsed = parsePlain(text) end + if not parsed then return false end + cache[tk] = parsed + evictCache() + noctalia.state.set("lyrics", parsed) + return true + end + + local function fetchCustom() + if customUrl == "" then + inFlight = nil + noctalia.state.set("lyrics", nil) + return + end + + local replacements = { + title = track.title, + artist = track.artist, + album = track.album, + duration = tostring(math.floor((track.duration or 0) / 1000000)), + } + local url = customUrl:gsub("{([%w_]+)}", function(key) + return noctalia.string.urlEncode(replacements[key] or "") + end) + + noctalia.http({ url = url, headers = { "Accept: application/json, text/plain" } }, function(response) + if tk ~= lastTrackKey then inFlight = nil; return end + local text = response.ok and response.body or "" + if text ~= "" and customJsonField ~= "" then + local decoded = noctalia.json.decode(text) + for part in customJsonField:gmatch("[^.]+") do + decoded = type(decoded) == "table" and decoded[part] or nil + end + if type(decoded) == "table" then + cache[tk] = decoded + evictCache() + noctalia.state.set("lyrics", decoded) + inFlight = nil + return + end + text = type(decoded) == "string" and decoded or "" + end + applyText(text) + inFlight = nil + end) + end + + if lyricsSource == "external" then + inFlight = nil + return + elseif lyricsSource == "mpris" then + applyText(embeddedLyrics) + inFlight = nil + return + elseif lyricsSource == "custom" then + fetchCustom() + return + elseif lyricsSource == "netease" then + tryFetch(track.title .. " " .. track.artist, function() + tryFetch(track.title, nil) + end) + return + end + + -- Auto: LRCLIB, then the public NetEase API. + runPy("lrclib_lyric.py", function(parsed) + if applyParsed(parsed) then inFlight = nil; return end + if lyricsSource == "lrclib" then + inFlight = nil + noctalia.state.set("lyrics", nil) + return + end + tryFetch(track.title .. " " .. track.artist, function() + tryFetch(track.title, nil) + end) + end) +end + +local function fetchCover(track, artUrl) + if coverInFlight then return end + coverInFlight = track.title .. "|" .. track.artist .. "|" .. track.album + + local dest = coverPathFor(track) + + local apply = function(path) + local tk = track.title .. "|" .. track.artist .. "|" .. track.album + coverInFlight = nil + if tk ~= lastTrackKey then return end + coverCache[tk] = path + noctalia.state.set("cover", path) + end + + if not artUrl or artUrl == "" then + noctalia.state.set("cover", nil) + coverInFlight = nil + return + end + + if artUrl:sub(1, 7) == "file://" then + local source = noctalia.string.urlDecode(artUrl:sub(8)) + if not noctalia.fileExists(source) then + apply(nil) + return + end + noctalia.runAsync("cp -- " .. shellQuote(source) .. " " .. shellQuote(dest), function(result) + if result.exitCode == 0 then apply(dest) else apply(source) end + end) + return + end + + noctalia.download(artUrl, dest, function(ok) + if ok then apply(dest) else apply(nil) end + end) +end + +local function poll() + local cmd = [[playerctl metadata --format $'{{lc(status)}}\x1f{{title}}\x1f{{artist}}\x1f{{album}}\x1f{{position}}\x1f{{mpris:length}}\x1f{{mpris:artUrl}}\x1f{{xesam:asText}}' 2>/dev/null]] + + noctalia.runAsync(cmd, function(r) + if r.exitCode ~= 0 or not r.stdout or r.stdout == "" then + noctalia.state.set("track", nil) + noctalia.state.set("lyrics", nil) + noctalia.state.set("cover", nil) + noctalia.state.set("playing", false) + return + end + + local parts = {} + local separator = string.char(31) + for field in (r.stdout .. separator):gmatch("(.-)" .. separator) do + parts[#parts + 1] = field:gsub("^%s+", ""):gsub("%s+$", "") + end + + local status = parts[1] or "stopped" + local title = parts[2] or "" + local artist = parts[3] or "" + local album = parts[4] or "" + local artUrl = parts[7] or "" + local embeddedLyrics = parts[8] or "" + + if title == "" and artist == "" then + noctalia.state.set("track", nil) + noctalia.state.set("lyrics", nil) + noctalia.state.set("playing", status == "playing") + return + end + + local playing = status == "playing" + local tk = title .. "|" .. artist .. "|" .. album + + local t = { + title = title, + artist = artist, + album = album, + status = status, + position = tonumber(parts[5]) or 0, + duration = tonumber(parts[6]) or 0, + } + currentTrack = t + currentEmbeddedLyrics = embeddedLyrics + + noctalia.state.set("position", t.position) + + if tk ~= lastTrackKey then + lastTrackKey = tk + noctalia.state.set("track", t) + noctalia.state.set("playing", playing) + + local cached = cache[tk] + if cached then + noctalia.state.set("lyrics", cached) + else + noctalia.state.set("lyrics", nil) + fetchLyricsNetEase(t, embeddedLyrics) + end + + local cachedCover = coverCache[tk] + if cachedCover then + noctalia.state.set("cover", cachedCover) + else + noctalia.state.set("cover", nil) + fetchCover(t, artUrl) + end + else + noctalia.state.set("track", t) + noctalia.state.set("playing", playing) + end + end) +end + +local pollTick = 0 + +function update() + if lyricsSource == "external" then return end + pollTick = pollTick + 1 + if pollTick % 2 == 0 then + poll() + end + +end + +function onConfigChanged() + local nextSource = noctalia.getConfig("lyrics_source") or "auto" + local nextUrl = noctalia.getConfig("custom_url") or "" + local nextField = noctalia.getConfig("custom_json_field") or "syncedLyrics" + local sourceChanged = nextSource ~= lyricsSource or nextUrl ~= customUrl or nextField ~= customJsonField + lyricsSource = nextSource + customUrl = nextUrl + customJsonField = nextField + if sourceChanged and currentTrack then + inFlight = nil + cache = {} + noctalia.state.set("lyrics", nil) + fetchLyricsNetEase(currentTrack, currentEmbeddedLyrics) + end +end + +local function applyPushedLyrics(payload) + local decoded = noctalia.json.decode(payload or "") + if type(decoded) == "table" then + if decoded.track then + currentTrack = decoded.track + lastTrackKey = (decoded.track.title or "") .. "|" .. (decoded.track.artist or "") .. "|" .. (decoded.track.album or "") + noctalia.state.set("track", decoded.track) + end + if decoded.lines then noctalia.state.set("lyrics", decoded.lines) end + if decoded.lyrics then + local parsed = parseLRC(decoded.lyrics) or parsePlain(decoded.lyrics) + noctalia.state.set("lyrics", parsed) + end + if decoded.position ~= nil then noctalia.state.set("position", decoded.position) end + if decoded.playing ~= nil then noctalia.state.set("playing", decoded.playing == true) end + if decoded.cover ~= nil then noctalia.state.set("cover", decoded.cover) end + return true + end + return false +end + +function onIpc(event, payload) + if event == "push-lrc" then + noctalia.state.set("lyrics", parseLRC(payload or "") or parsePlain(payload or "")) + elseif event == "push-json" or event == "push-state" then + applyPushedLyrics(payload) + elseif event == "clear" then + noctalia.state.set("lyrics", nil) + end +end + +if lyricsSource ~= "external" then poll() end diff --git a/lyrics/plugin.toml b/lyrics/plugin.toml new file mode 100644 index 0000000..70689ac --- /dev/null +++ b/lyrics/plugin.toml @@ -0,0 +1,152 @@ +id = "h465855hgg/lyrics" +name = "Lyrics" +version = "1.0.0" +plugin_api = 3 +author = "h465855hgg" +license = "MIT" +dependencies = ["playerctl", "python3", "curl", "cp"] +tags = ["bar", "service", "music", "media", "animation"] +icon = "music" +description = "Synchronized lyrics with karaoke highlighting, animated transitions, and flexible lyric sources." + +[[setting]] +key = "lyrics_source" +type = "select" +label_key = "settings.lyrics_source.label" +description_key = "settings.lyrics_source.description" +default = "auto" +options = [ + { value = "auto", label_key = "settings.lyrics_source.options.auto" }, + { value = "lrclib", label_key = "settings.lyrics_source.options.lrclib" }, + { value = "netease", label_key = "settings.lyrics_source.options.netease" }, + { value = "mpris", label_key = "settings.lyrics_source.options.mpris" }, + { value = "custom", label_key = "settings.lyrics_source.options.custom" }, + { value = "external", label_key = "settings.lyrics_source.options.external" }, +] + +[[setting]] +key = "custom_url" +type = "string" +label_key = "settings.custom_url.label" +description_key = "settings.custom_url.description" +default = "" +visible_when = { key = "lyrics_source", values = ["custom"] } + +[[setting]] +key = "custom_json_field" +type = "string" +label_key = "settings.custom_json_field.label" +description_key = "settings.custom_json_field.description" +default = "syncedLyrics" +visible_when = { key = "lyrics_source", values = ["custom"] } + +[[setting]] +key = "cue_text" +type = "string" +label_key = "settings.cue_text.label" +description_key = "settings.cue_text.description" +default = "•••••" + +[[setting]] +key = "scroll_mode" +type = "select" +label_key = "settings.scroll_mode.label" +default = "auto" +description_key = "settings.scroll_mode.description" +options = [ + { value = "auto", label_key = "settings.scroll_mode.options.auto" }, + { value = "marquee", label_key = "settings.scroll_mode.options.marquee" }, + { value = "static", label_key = "settings.scroll_mode.options.static" }, +] + +[[setting]] +key = "marquee_speed" +type = "int" +label_key = "settings.marquee_speed.label" +default = 30 +min = 10 +max = 120 +description_key = "settings.marquee_speed.description" + +[[setting]] +key = "max_lines" +type = "int" +label_key = "settings.max_lines.label" +default = 1 +min = 1 +max = 3 +description_key = "settings.max_lines.description" + +[[setting]] +key = "gradient" +type = "bool" +label_key = "settings.gradient.label" +default = true +description_key = "settings.gradient.description" + +[[setting]] +key = "animation" +type = "select" +label_key = "settings.animation.label" +default = "karaoke" +description_key = "settings.animation.description" +options = [ + { value = "karaoke", label_key = "settings.animation.options.karaoke" }, + { value = "cascade", label_key = "settings.animation.options.cascade" }, + { value = "wave", label_key = "settings.animation.options.wave" }, + { value = "fade", label_key = "settings.animation.options.fade" }, + { value = "none", label_key = "settings.animation.options.none" }, +] + +[[setting]] +key = "max_chars" +type = "int" +label_key = "settings.max_chars.label" +default = 24 +min = 8 +max = 80 +description_key = "settings.max_chars.description" + +[[setting]] +key = "char_width" +type = "int" +label_key = "settings.char_width.label" +default = 9 +min = 4 +max = 24 +description_key = "settings.char_width.description" + +# Headless background service: polls MPRIS metadata, fetches lyrics, publishes state. +[[service]] +id = "service" +entry = "lyrics_service.luau" + +# Bar widget: thin presentation that mirrors the published lyrics state. +[[widget]] +id = "lyrics" +entry = "lyrics.luau" + + [[widget.setting]] + key = "glyph" + type = "glyph" + label_key = "settings.glyph.label" + default = "music" + + [[widget.setting]] + key = "show_artist" + type = "bool" + label_key = "settings.show_artist.label" + default = true + + [[widget.setting]] + key = "hide_when_paused" + type = "bool" + label_key = "settings.hide_when_paused.label" + default = false + + [[widget.setting]] + key = "show_cover" + type = "bool" + label_key = "settings.show_cover.label" + description_key = "settings.show_cover.description" + default = true diff --git a/lyrics/thumbnail.webp b/lyrics/thumbnail.webp new file mode 100644 index 0000000000000000000000000000000000000000..dd51510f4d93d68ae5e6836458144830e607dad5 GIT binary patch literal 13748 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 a866NPk^q-sEQ}ru3|xy=*&hINkqH2C1d{Fm literal 0 HcmV?d00001 diff --git a/lyrics/translations/en.json b/lyrics/translations/en.json new file mode 100644 index 0000000..6c0a6d5 --- /dev/null +++ b/lyrics/translations/en.json @@ -0,0 +1,85 @@ +{ + "title": "Lyrics", + "no_lyrics": "♪ No lyrics available", + "intro": "Intro", + "instrumental": "Instrumental", + "settings": { + "glyph": { + "label": "Glyph" + }, + "show_artist": { + "label": "Show artist" + }, + "hide_when_paused": { + "label": "Hide when paused" + }, + "show_cover": { + "label": "Show album cover", + "description": "Display the song's album art next to the lyrics." + }, + "lyrics_source": { + "label": "Lyrics source", + "description": "Choose a preset source, local-player lyrics, a custom endpoint, or external push protocol.", + "options": { + "auto": "Automatic fallback", + "lrclib": "LRCLIB", + "netease": "NetEase Music (public API)", + "mpris": "Local player (MPRIS)", + "custom": "Custom HTTP endpoint", + "external": "External IPC push" + } + }, + "custom_url": { + "label": "Custom endpoint URL", + "description": "Supports {title}, {artist}, {album}, and {duration} placeholders. Text responses may contain LRC directly." + }, + "custom_json_field": { + "label": "JSON lyrics field", + "description": "Lyrics field in a JSON response, with dotted paths such as data.lyric. Leave empty for plain LRC." + }, + "cue_text": { + "label": "Intro/interlude characters", + "description": "Text or characters highlighted during intros and interludes." + }, + "scroll_mode": { + "label": "Scroll mode", + "description": "How lyrics scroll in the bar.", + "options": { + "auto": "Auto (synced)", + "marquee": "Marquee", + "static": "Static" + } + }, + "marquee_speed": { + "label": "Marquee speed", + "description": "Pixels per second for long-line scrolling." + }, + "max_lines": { + "label": "Max lines", + "description": "Maximum lyric lines to show at once." + }, + "gradient": { + "label": "Per-character gradient", + "description": "Light up each character as the song progresses (karaoke style)." + }, + "animation": { + "label": "Animation", + "description": "How lyrics animate on line change.", + "options": { + "karaoke": "Karaoke gradient + fade", + "cascade": "Character cascade", + "wave": "Character wave reveal", + "fade": "Fade only", + "none": "No animation" + } + }, + "max_chars": { + "label": "Max characters", + "description": "Visible width before a long lyric line scrolls (marquee)." + }, + "char_width": { + "label": "Character width (px)", + "description": "Approximate pixel width per character, used to fix the widget width and clip scrolling." + } + } +} From 0d2adc1939ecd85bdc8c53b2a58fe80e6e64a779 Mon Sep 17 00:00:00 2001 From: h465855hgg <3382198490@qq.com> Date: Fri, 17 Jul 2026 05:57:13 +0800 Subject: [PATCH 2/6] docs: add plugin screenshots --- lyrics/README.md | 10 ++++++++++ lyrics/screenshots/settings.webp | Bin 0 -> 47850 bytes lyrics/screenshots/widget.webp | Bin 0 -> 8910 bytes lyrics/thumbnail.webp | Bin 13748 -> 7560 bytes 4 files changed, 10 insertions(+) create mode 100644 lyrics/screenshots/settings.webp create mode 100644 lyrics/screenshots/widget.webp diff --git a/lyrics/README.md b/lyrics/README.md index 58dd762..6baaaf5 100644 --- a/lyrics/README.md +++ b/lyrics/README.md @@ -30,6 +30,16 @@ When synchronized lyrics are unavailable, the widget displays `track title + artist`. Long lines pause at each end while scrolling. Intro and instrumental gaps can show a configurable cue such as `•••••`. +## Screenshots + +Status-bar widget: + +![Lyrics bar widget](screenshots/widget.webp) + +Plugin settings: + +![Lyrics settings](screenshots/settings.webp) + ## Settings | Setting | Type | Default | Description | diff --git a/lyrics/screenshots/settings.webp b/lyrics/screenshots/settings.webp new file mode 100644 index 0000000000000000000000000000000000000000..fd049ad2dc306c4a69622102818cd1fe9d877b8d GIT binary patch literal 47850 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 Mi@J$gO92A|0HniL2LJ#7 literal 0 HcmV?d00001 diff --git a/lyrics/screenshots/widget.webp b/lyrics/screenshots/widget.webp new file mode 100644 index 0000000000000000000000000000000000000000..f85b7840fd7fe929651e8e1bdb723cc83e93d1c9 GIT binary patch literal 8910 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 literal 13748 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 a866NPk^q-sEQ}ru3|xy=*&hINkqH2C1d{Fm From cf3a93b2fb9bc3726b8e64b128b3ee000b23a87d Mon Sep 17 00:00:00 2001 From: h465855hgg <3382198490@qq.com> Date: Fri, 17 Jul 2026 06:21:54 +0800 Subject: [PATCH 3/6] docs: use generated plugin thumbnail --- lyrics/thumbnail.webp | Bin 7560 -> 41594 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/lyrics/thumbnail.webp b/lyrics/thumbnail.webp index f2269ed9464792ca86e4cc154d1b0f691b7bfd43..cf876db65e015f8c943b9f529b71a1436d372ff4 100644 GIT binary patch literal 41594 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 From 9eb698403110cbba09aea23ec012a06316f7772f Mon Sep 17 00:00:00 2001 From: h465855hgg <3382198490@qq.com> Date: Fri, 17 Jul 2026 07:20:42 +0800 Subject: [PATCH 4/6] docs: add lyrics dependency setup helper --- lyrics/README.md | 11 +++ lyrics/scripts/setup-deps.sh | 149 +++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100755 lyrics/scripts/setup-deps.sh diff --git a/lyrics/README.md b/lyrics/README.md index 6baaaf5..a7dc19d 100644 --- a/lyrics/README.md +++ b/lyrics/README.md @@ -15,6 +15,17 @@ highlighting, animated line changes, and configurable online or local sources. Install `playerctl`, `python3`, `curl`, and `cp` on `PATH`. The active media player must expose MPRIS metadata for automatic track and playback detection. +Noctalia installs the plugin files; it does not install system packages for you. +To check or install the runtime packages automatically, run: + +```sh +sh scripts/setup-deps.sh --check +sh scripts/setup-deps.sh +``` + +Use `--yes` for unattended installs. The script supports `apt`, `dnf`, +`pacman`, `zypper`, `apk`, and `xbps-install`. + ## Usage Enable `h465855hgg/lyrics`, then add the `lyrics` bar widget in Noctalia's bar diff --git a/lyrics/scripts/setup-deps.sh b/lyrics/scripts/setup-deps.sh new file mode 100755 index 0000000..5493be4 --- /dev/null +++ b/lyrics/scripts/setup-deps.sh @@ -0,0 +1,149 @@ +#!/usr/bin/env sh +set -eu + +usage() { + cat <<'EOF' +Usage: scripts/setup-deps.sh [--check] [--yes] + +Install or check runtime dependencies for the Noctalia Lyrics plugin. + +Options: + --check Only report missing commands; do not install anything. + --yes Skip the confirmation prompt before installing packages. + --help Show this help text. +EOF +} + +CHECK_ONLY=0 +ASSUME_YES=0 + +while [ "$#" -gt 0 ]; do + case "$1" in + --check) + CHECK_ONLY=1 + ;; + -y|--yes) + ASSUME_YES=1 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "Unknown option: $1" >&2 + usage >&2 + exit 2 + ;; + esac + shift +done + +need_command() { + command -v "$1" >/dev/null 2>&1 || MISSING_COMMANDS="$MISSING_COMMANDS $1" +} + +MISSING_COMMANDS="" +need_command playerctl +need_command python3 +need_command curl +need_command cp + +if [ -z "$MISSING_COMMANDS" ]; then + echo "All runtime commands are installed: playerctl python3 curl cp" + exit 0 +fi + +echo "Missing runtime command(s):$MISSING_COMMANDS" + +if [ "$CHECK_ONLY" -eq 1 ]; then + exit 1 +fi + +if [ "$(id -u)" -eq 0 ]; then + SUDO="" +elif command -v sudo >/dev/null 2>&1; then + SUDO="sudo" +else + echo "sudo is required to install packages as a non-root user." >&2 + exit 1 +fi + +detect_pm() { + if command -v apt-get >/dev/null 2>&1; then + echo apt + elif command -v dnf >/dev/null 2>&1; then + echo dnf + elif command -v pacman >/dev/null 2>&1; then + echo pacman + elif command -v zypper >/dev/null 2>&1; then + echo zypper + elif command -v apk >/dev/null 2>&1; then + echo apk + elif command -v xbps-install >/dev/null 2>&1; then + echo xbps + else + echo unknown + fi +} + +PM="$(detect_pm)" + +case "$PM" in + apt) + INSTALL_CMD="$SUDO apt-get update && $SUDO apt-get install -y playerctl python3 curl coreutils" + ;; + dnf) + INSTALL_CMD="$SUDO dnf install -y playerctl python3 curl coreutils" + ;; + pacman) + INSTALL_CMD="$SUDO pacman -S --needed playerctl python curl coreutils" + ;; + zypper) + INSTALL_CMD="$SUDO zypper install -y playerctl python3 curl coreutils" + ;; + apk) + INSTALL_CMD="$SUDO apk add playerctl python3 curl coreutils" + ;; + xbps) + INSTALL_CMD="$SUDO xbps-install -Sy playerctl python3 curl coreutils" + ;; + *) + cat >&2 <<'EOF' +Could not detect a supported package manager. +Install these packages manually with your distribution package manager: + playerctl python3 curl coreutils +EOF + exit 1 + ;; +esac + +echo "Detected package manager: $PM" +echo "Install command: $INSTALL_CMD" + +if [ "$ASSUME_YES" -ne 1 ]; then + printf "Proceed with installation? [y/N] " + read -r answer + case "$answer" in + y|Y|yes|YES) + ;; + *) + echo "Cancelled." + exit 1 + ;; + esac +fi + +sh -c "$INSTALL_CMD" + +MISSING_COMMANDS="" +need_command playerctl +need_command python3 +need_command curl +need_command cp + +if [ -n "$MISSING_COMMANDS" ]; then + echo "Still missing after installation:$MISSING_COMMANDS" >&2 + exit 1 +fi + +echo "Dependencies installed successfully." From 6b96da5a0cf35348de53e7636e68476f603f5be9 Mon Sep 17 00:00:00 2001 From: h465855hgg <3382198490@qq.com> Date: Fri, 17 Jul 2026 14:49:39 +0800 Subject: [PATCH 5/6] feat(lyrics): add customizable colors --- lyrics/README.md | 2 ++ lyrics/lyrics.luau | 14 ++++++++------ lyrics/plugin.toml | 16 +++++++++++++++- lyrics/translations/en.json | 8 ++++++++ 4 files changed, 33 insertions(+), 7 deletions(-) diff --git a/lyrics/README.md b/lyrics/README.md index a7dc19d..3cd29c9 100644 --- a/lyrics/README.md +++ b/lyrics/README.md @@ -70,6 +70,8 @@ Plugin settings: | `show_artist` | `bool` | `true` | Includes the artist in track-information mode. | | `hide_when_paused` | `bool` | `false` | Hides the widget instead of dimming it while paused. | | `show_cover` | `bool` | `true` | Shows circular album artwork beside the lyrics. | +| `active_color` | `color` | `primary` | Colors the current and already-sung lyric characters. | +| `inactive_color` | `color` | `on_surface_variant` | Colors upcoming lyrics, paused playback, and secondary lines. | ## IPC diff --git a/lyrics/lyrics.luau b/lyrics/lyrics.luau index bb9a4cd..c352031 100644 --- a/lyrics/lyrics.luau +++ b/lyrics/lyrics.luau @@ -8,6 +8,8 @@ local showArtist = noctalia.getConfig("show_artist") local hideWhenPaused = noctalia.getConfig("hide_when_paused") local showCover = noctalia.getConfig("show_cover") if showCover == nil then showCover = true end +local activeColor = noctalia.getConfig("active_color") or "primary" +local inactiveColor = noctalia.getConfig("inactive_color") or "on_surface_variant" -- These are plugin settings, not per-widget settings. local scrollMode = noctalia.getConfig("scroll_mode") or "auto" @@ -189,9 +191,9 @@ local function getMarqueeOffset(length) end local function karaokeColor(charTime, charProgress, position, useGradient) - if not playing then return "on_surface_variant" end - local active = noctalia.isDarkMode() and "primary" or "on_surface" - local inactive = "on_surface_variant" + if not playing then return inactiveColor end + local active = activeColor + local inactive = inactiveColor if charTime and position then if not useGradient then return position >= charTime and active or inactive @@ -230,8 +232,8 @@ local function buildLineRow(line, opts) local labels = {} for sourceIndex = first, last do - local active = playing and (noctalia.isDarkMode() and "primary" or "on_surface") or "on_surface_variant" - local color = opts.dim and "on_surface_variant" or active + local active = playing and activeColor or inactiveColor + local color = opts.dim and inactiveColor or active if not opts.solid and not opts.dim then local progress = #chars > 1 and (sourceIndex - 1) / (#chars - 1) or 0 color = karaokeColor(times and times[sourceIndex], progress, opts.position, opts.useGradient) @@ -316,7 +318,7 @@ local function render() prefix[#prefix + 1] = ui.glyph({ name = glyph, size = 14, - color = playing and (noctalia.isDarkMode() and "primary" or "on_surface") or "on_surface_variant", + color = playing and activeColor or inactiveColor, }) end diff --git a/lyrics/plugin.toml b/lyrics/plugin.toml index 70689ac..37eb261 100644 --- a/lyrics/plugin.toml +++ b/lyrics/plugin.toml @@ -1,6 +1,6 @@ id = "h465855hgg/lyrics" name = "Lyrics" -version = "1.0.0" +version = "1.1.0" plugin_api = 3 author = "h465855hgg" license = "MIT" @@ -150,3 +150,17 @@ entry = "lyrics.luau" label_key = "settings.show_cover.label" description_key = "settings.show_cover.description" default = true + + [[widget.setting]] + key = "active_color" + type = "color" + label_key = "settings.active_color.label" + description_key = "settings.active_color.description" + default = "primary" + + [[widget.setting]] + key = "inactive_color" + type = "color" + label_key = "settings.inactive_color.label" + description_key = "settings.inactive_color.description" + default = "on_surface_variant" diff --git a/lyrics/translations/en.json b/lyrics/translations/en.json index 6c0a6d5..ac28055 100644 --- a/lyrics/translations/en.json +++ b/lyrics/translations/en.json @@ -17,6 +17,14 @@ "label": "Show album cover", "description": "Display the song's album art next to the lyrics." }, + "active_color": { + "label": "Active lyric color", + "description": "Color used for the current and already-sung lyric characters." + }, + "inactive_color": { + "label": "Inactive lyric color", + "description": "Color used for upcoming lyrics, paused playback, and secondary lines." + }, "lyrics_source": { "label": "Lyrics source", "description": "Choose a preset source, local-player lyrics, a custom endpoint, or external push protocol.", From 6dacdc7a781362b4eb51b6fa58555f5505b93a35 Mon Sep 17 00:00:00 2001 From: h465855hgg <3382198490@qq.com> Date: Fri, 17 Jul 2026 21:57:02 +0800 Subject: [PATCH 6/6] fix(lyrics): avoid shell injection in NetEase requests --- lyrics/README.md | 10 +++++----- lyrics/lyrics_service.luau | 23 +++++++++++++---------- lyrics/plugin.toml | 2 +- lyrics/scripts/setup-deps.sh | 18 ++++++++---------- 4 files changed, 27 insertions(+), 26 deletions(-) diff --git a/lyrics/README.md b/lyrics/README.md index 3cd29c9..86ce6e7 100644 --- a/lyrics/README.md +++ b/lyrics/README.md @@ -12,7 +12,7 @@ highlighting, animated line changes, and configurable online or local sources. ## Requirements -Install `playerctl`, `python3`, `curl`, and `cp` on `PATH`. The active media +Install `playerctl`, `python3`, and `cp` on `PATH`. The active media player must expose MPRIS metadata for automatic track and playback detection. Noctalia installs the plugin files; it does not install system packages for you. @@ -103,7 +103,7 @@ HTTP mode contacts only the configured endpoint. The plugin never reads browser cookies or player credentials. The service runs `playerctl` to read and control MPRIS playback, `python3` for the -LRCLIB helper and dynamic-lyric parser, `curl` for the public NetEase API, and -`cp` to preserve temporary local cover files. Query scratch files and downloaded -cover images are written inside the plugin runtime directory. Remote code is -never downloaded or executed. +LRCLIB helper and dynamic-lyric parser, and `cp` to preserve temporary local cover +files. Public NetEase requests use Noctalia's HTTP API. Query scratch files and +downloaded cover images are written inside the plugin runtime directory. Remote +code is never downloaded or executed. diff --git a/lyrics/lyrics_service.luau b/lyrics/lyrics_service.luau index 3368540..119add0 100644 --- a/lyrics/lyrics_service.luau +++ b/lyrics/lyrics_service.luau @@ -82,19 +82,18 @@ local function fetchLyricsNetEase(track, embeddedLyrics) local function tryFetch(query, fallback) local searchUrl = "https://music.163.com/api/search/get?type=1&s=" .. noctalia.string.urlEncode(query) .. "&limit=5" - local cmd = 'curl -s --max-time 10 --connect-timeout 5 "' .. searchUrl .. '" -H "Referer: https://music.163.com"' - noctalia.runAsync(cmd, function(r1) + noctalia.http({ url = searchUrl, headers = { "Referer: https://music.163.com" } }, function(r1) if not inFlight then return end if tk ~= lastTrackKey then inFlight = nil; return end - if r1.exitCode ~= 0 or not r1.stdout or #r1.stdout == 0 then + if not r1.ok or r1.status < 200 or r1.status >= 300 or not r1.body or #r1.body == 0 then if fallback then fallback() else inFlight = nil; noctalia.state.set("lyrics", nil) end return end - local data = noctalia.json.decode(r1.stdout) + local data = noctalia.json.decode(r1.body) if not data or not data.result or not data.result.songs or #data.result.songs == 0 then if fallback then fallback() else inFlight = nil; noctalia.state.set("lyrics", nil) end @@ -120,17 +119,21 @@ local function fetchLyricsNetEase(track, embeddedLyrics) bestMatch = data.result.songs[1] end - local songId = bestMatch.id - local lyricUrl = "https://music.163.com/api/song/lyric?id=" .. songId .. "&lv=1&kv=1&tv=-1" - local lCmd = 'curl -s --max-time 10 --connect-timeout 5 "' .. lyricUrl .. '" -H "Referer: https://music.163.com"' + local songId = tostring(bestMatch.id or "") + if not songId:match("^%d+$") then + if fallback then fallback() + else inFlight = nil; noctalia.state.set("lyrics", nil) end + return + end + local lyricUrl = "https://music.163.com/api/song/lyric?id=" .. noctalia.string.urlEncode(songId) .. "&lv=1&kv=1&tv=-1" - noctalia.runAsync(lCmd, function(r2) + noctalia.http({ url = lyricUrl, headers = { "Referer: https://music.163.com" } }, function(r2) if not inFlight then return end if tk ~= lastTrackKey then inFlight = nil; return end local lyrics = nil - if r2.exitCode == 0 and r2.stdout and #r2.stdout > 0 then - local ldata = noctalia.json.decode(r2.stdout) + if r2.ok and r2.status >= 200 and r2.status < 300 and r2.body and #r2.body > 0 then + local ldata = noctalia.json.decode(r2.body) local klyricStr = "" if ldata and ldata.klyric then local k = ldata.klyric diff --git a/lyrics/plugin.toml b/lyrics/plugin.toml index 37eb261..6f7837b 100644 --- a/lyrics/plugin.toml +++ b/lyrics/plugin.toml @@ -4,7 +4,7 @@ version = "1.1.0" plugin_api = 3 author = "h465855hgg" license = "MIT" -dependencies = ["playerctl", "python3", "curl", "cp"] +dependencies = ["playerctl", "python3", "cp"] tags = ["bar", "service", "music", "media", "animation"] icon = "music" description = "Synchronized lyrics with karaoke highlighting, animated transitions, and flexible lyric sources." diff --git a/lyrics/scripts/setup-deps.sh b/lyrics/scripts/setup-deps.sh index 5493be4..08b5bd0 100755 --- a/lyrics/scripts/setup-deps.sh +++ b/lyrics/scripts/setup-deps.sh @@ -45,11 +45,10 @@ need_command() { MISSING_COMMANDS="" need_command playerctl need_command python3 -need_command curl need_command cp if [ -z "$MISSING_COMMANDS" ]; then - echo "All runtime commands are installed: playerctl python3 curl cp" + echo "All runtime commands are installed: playerctl python3 cp" exit 0 fi @@ -90,28 +89,28 @@ PM="$(detect_pm)" case "$PM" in apt) - INSTALL_CMD="$SUDO apt-get update && $SUDO apt-get install -y playerctl python3 curl coreutils" + INSTALL_CMD="$SUDO apt-get update && $SUDO apt-get install -y playerctl python3 coreutils" ;; dnf) - INSTALL_CMD="$SUDO dnf install -y playerctl python3 curl coreutils" + INSTALL_CMD="$SUDO dnf install -y playerctl python3 coreutils" ;; pacman) - INSTALL_CMD="$SUDO pacman -S --needed playerctl python curl coreutils" + INSTALL_CMD="$SUDO pacman -S --needed playerctl python coreutils" ;; zypper) - INSTALL_CMD="$SUDO zypper install -y playerctl python3 curl coreutils" + INSTALL_CMD="$SUDO zypper install -y playerctl python3 coreutils" ;; apk) - INSTALL_CMD="$SUDO apk add playerctl python3 curl coreutils" + INSTALL_CMD="$SUDO apk add playerctl python3 coreutils" ;; xbps) - INSTALL_CMD="$SUDO xbps-install -Sy playerctl python3 curl coreutils" + INSTALL_CMD="$SUDO xbps-install -Sy playerctl python3 coreutils" ;; *) cat >&2 <<'EOF' Could not detect a supported package manager. Install these packages manually with your distribution package manager: - playerctl python3 curl coreutils + playerctl python3 coreutils EOF exit 1 ;; @@ -138,7 +137,6 @@ sh -c "$INSTALL_CMD" MISSING_COMMANDS="" need_command playerctl need_command python3 -need_command curl need_command cp if [ -n "$MISSING_COMMANDS" ]; then