Files
XoséandClaude Opus 5.5 13f29e26c4 Plexamp Lite 1.14: Android 4.1 build with ExoPlayer, lyrics, home-screen widget
- One build per Android level, as in Tenda: build/PlexampLite.apk (Android 2.2+, versionCode 1508) and
  build/PlexampLite-api16.apk (Android 4.1+, 1516), from shared src/ plus platform/api8 or platform/api16.
- Android 4.1 build: ExoPlayer 2.18.7 behind a small Engine interface (gapless hand-over to read-ahead and
  downloaded files, a longer buffer, MediaPlayer fallback for tracks it can't decode), a notification and
  lock screen with art and buttons, a resizable widget, Holo, a menu button without a Menu key, metered networks.
  R8 shrinks ExoPlayer and Guava (tools/fetch_exoplayer.sh, tools/r8-rules.pro).
- Both builds: lyrics in Now Playing as in the Mac app (timed lyrics follow and seek), a home-screen widget,
  media play/pause keys, the moon icon drawn without clipPath.
- PlexampLite-noreport on the SD card stops play reports, for tests against a real server.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-01 18:41:26 +01:00

41 lines
2.0 KiB
Java

import java.util.List;
import com.minamp.util.Lrc;
/** LRC and plain-text lyrics parsing (com.minamp.util.Lrc). Run:
* javac -d /tmp/lt src/com/minamp/util/Lrc.java test/LyricsTest.java && java -cp /tmp/lt LyricsTest */
public class LyricsTest {
static int fails;
static void check(boolean ok, String what) {
System.out.println((ok ? "PASS " : "FAIL ") + what);
if (!ok) fails++;
}
public static void main(String[] a) {
boolean[] synced = new boolean[1];
List<Lrc.Line> l = Lrc.parse("[ar:Pereza]\n[ti:Pompa]\n[00:12.50]First\r\n[00:05]Zero\n[01:02.123][00:20.00]Twice\n", synced);
check(synced[0], "timed lyrics are synced");
check(l.size() == 4, "a line with two stamps counts twice, tags are dropped (" + l.size() + ")");
check(l.get(0).time == 5000 && l.get(0).text.equals("Zero"), "sorted by time");
check(l.get(1).time == 12500, "hundredths");
check(l.get(3).time == 62123 && l.get(3).text.equals("Twice"), "milliseconds");
check(Lrc.lineAt(l, 4000) == -1, "before the first line");
check(Lrc.lineAt(l, 13000) == 1, "line being sung");
check(Lrc.lineAt(l, 999999) == 3, "after the last line");
l = Lrc.parse("[offset:+500]\n[00:10.00]A <00:10.50>word <00:11.00>by word\n", synced);
check(l.size() == 1 && l.get(0).time == 9500, "offset shows lines earlier");
check(l.get(0).text.equals("A word by word"), "word stamps removed: " + l.get(0).text);
l = Lrc.parse("\n\nVerse one\nline two\n\nVerse two\n\n", synced);
check(!synced[0], "plain text isn't synced");
check(l.size() == 4 && l.get(2).text.length() == 0, "blank lines between verses kept, at the ends dropped");
check(l.get(0).time == -1, "plain lines have no time");
check(Lrc.parse("", synced).isEmpty(), "empty text, no lines");
System.out.println(fails == 0 ? "all passed" : fails + " failed");
System.exit(fails == 0 ? 0 : 1);
}
}