193 lines
6.6 KiB
Nix
193 lines
6.6 KiB
Nix
{ lib, ... }:
|
|
let
|
|
ocrContent = "Music Test";
|
|
musicFile = "test.mp3";
|
|
|
|
ocrPauseColor = "#FF00FF";
|
|
ocrStartColor = "#00FFFF";
|
|
in
|
|
{
|
|
name = "lomiri-music-app-standalone";
|
|
meta = {
|
|
maintainers = lib.teams.lomiri.members;
|
|
# This needs a Linux VM
|
|
platforms = lib.platforms.linux;
|
|
};
|
|
|
|
nodes.machine =
|
|
{ config, pkgs, ... }:
|
|
{
|
|
imports = [
|
|
./common/auto.nix
|
|
./common/user-account.nix
|
|
./common/x11.nix
|
|
];
|
|
|
|
services.xserver.enable = true;
|
|
|
|
environment = {
|
|
# Setup video
|
|
etc."${musicFile}".source =
|
|
pkgs.runCommand musicFile
|
|
{
|
|
nativeBuildInputs = with pkgs; [
|
|
ffmpeg # produce music
|
|
(imagemagick.override { ghostscriptSupport = true; }) # produce OCR-able cover image
|
|
];
|
|
}
|
|
''
|
|
magick -size 400x400 canvas:white -pointsize 40 -fill black -annotate +100+100 '${ocrContent}' output.png
|
|
ffmpeg -re \
|
|
-f lavfi -i anullsrc=channel_layout=mono:sample_rate=44100 \
|
|
-i output.png \
|
|
-map 0:0 -map 1:0 \
|
|
-id3v2_version 3 \
|
|
-metadata:s:v title="Album cover" \
|
|
-metadata:s:v comment="Cover (front)" \
|
|
-t 120 \
|
|
$out -loglevel fatal
|
|
'';
|
|
|
|
systemPackages =
|
|
with pkgs;
|
|
[
|
|
xdg-user-dirs # generate XDG dirs
|
|
xdotool # mouse movement
|
|
]
|
|
++ (with pkgs.lomiri; [
|
|
mediascanner2
|
|
lomiri-music-app
|
|
lomiri-thumbnailer
|
|
# To check if playback actually works, or is broken due to missing codecs, we need to make the app's icons more OCR-able
|
|
(lib.meta.hiPrio (
|
|
suru-icon-theme.overrideAttrs (oa: {
|
|
# Colour the background in special colours, which we can OCR for
|
|
postPatch =
|
|
(oa.postPatch or "")
|
|
+ ''
|
|
substituteInPlace suru/actions/scalable/media-playback-pause.svg \
|
|
--replace-fail 'fill:none' 'fill:${ocrPauseColor}'
|
|
|
|
substituteInPlace suru/actions/scalable/media-playback-start.svg \
|
|
--replace-fail 'fill:none' 'fill:${ocrStartColor}'
|
|
'';
|
|
})
|
|
))
|
|
]);
|
|
|
|
variables = {
|
|
UITK_ICON_THEME = "suru";
|
|
};
|
|
};
|
|
|
|
# Get mediascanner-2.0.service
|
|
services.desktopManager.lomiri.enable = lib.mkForce true;
|
|
|
|
# ...but stick with icewm
|
|
services.displayManager.defaultSession = lib.mkForce "none+icewm";
|
|
|
|
systemd.tmpfiles.settings = {
|
|
"10-lomiri-music-app-test-setup" = {
|
|
"/root/Music".d = {
|
|
mode = "0755";
|
|
user = "root";
|
|
group = "root";
|
|
};
|
|
"/root/Music/${musicFile}"."C+".argument = "/etc/${musicFile}";
|
|
};
|
|
};
|
|
|
|
i18n.supportedLocales = [ "all" ];
|
|
};
|
|
|
|
enableOCR = true;
|
|
|
|
testScript = ''
|
|
from collections.abc import Callable
|
|
import tempfile
|
|
import subprocess
|
|
|
|
pauseColor: str = "${ocrPauseColor}"
|
|
startColor: str = "${ocrStartColor}"
|
|
|
|
# Based on terminal-emulators.nix' check_for_pink
|
|
def check_for_color(color: str) -> Callable[[bool], bool]:
|
|
def check_for_color_retry(final=False) -> bool:
|
|
with tempfile.NamedTemporaryFile() as tmpin:
|
|
machine.send_monitor_command("screendump {}".format(tmpin.name))
|
|
|
|
cmd = 'convert {} -define histogram:unique-colors=true -format "%c" histogram:info:'.format(
|
|
tmpin.name
|
|
)
|
|
ret = subprocess.run(cmd, shell=True, capture_output=True)
|
|
if ret.returncode != 0:
|
|
raise Exception(
|
|
"image analysis failed with exit code {}".format(ret.returncode)
|
|
)
|
|
|
|
text = ret.stdout.decode("utf-8")
|
|
return color in text
|
|
|
|
return check_for_color_retry
|
|
|
|
machine.wait_for_x()
|
|
|
|
# mediascanner2 needs XDG dirs to exist
|
|
machine.succeed("xdg-user-dirs-update")
|
|
|
|
# mediascanner2 needs to have run, is only started automatically by Lomiri
|
|
machine.systemctl("start mediascanner-2.0.service", "root")
|
|
|
|
with subtest("lomiri music launches"):
|
|
machine.succeed("lomiri-music-app >&2 &")
|
|
machine.wait_for_text("favorite music")
|
|
machine.send_key("alt-f10")
|
|
machine.screenshot("lomiri-music")
|
|
|
|
with subtest("lomiri music plays music"):
|
|
machine.succeed("xdotool mousemove 30 720 click 1") # Skip intro
|
|
machine.wait_for_text("Albums")
|
|
machine.succeed("xdotool mousemove 25 45 click 1") # Open categories
|
|
machine.wait_for_text("Tracks")
|
|
machine.succeed("xdotool mousemove 25 240 click 1") # Switch to Tracks category
|
|
machine.wait_for_text("test") # the test file
|
|
machine.screenshot("lomiri-music_listing")
|
|
|
|
# Ensure pause colours isn't present already
|
|
assert (
|
|
check_for_color(pauseColor)(True) == False
|
|
), "pauseColor {} was present on the screen before we selected anything!".format(pauseColor)
|
|
|
|
machine.succeed("xdotool mousemove 25 120 click 1") # Select the track
|
|
|
|
# Waiting for pause icon to be displayed
|
|
with machine.nested("Waiting for the screen to have pauseColor {} on it:".format(pauseColor)):
|
|
retry(check_for_color(pauseColor))
|
|
|
|
machine.screenshot("lomiri-music_playback")
|
|
|
|
# Ensure play colours isn't present already
|
|
assert (
|
|
check_for_color(startColor)(True) == False
|
|
), "startColor {} was present on the screen before we were expecting it to be!".format(startColor)
|
|
|
|
machine.succeed("xdotool mousemove 860 480 click 1") # Pause track (only works if app can actually decode the file)
|
|
|
|
# Waiting for play icon to be displayed
|
|
with machine.nested("Waiting for the screen to have startColor {} on it:".format(startColor)):
|
|
retry(check_for_color(startColor))
|
|
|
|
machine.screenshot("lomiri-music_paused")
|
|
|
|
# Lastly, check if generated cover image got extracted properly
|
|
# if not, indicates an issue with mediascanner / lomiri-thumbnailer
|
|
machine.wait_for_text("${ocrContent}")
|
|
|
|
machine.succeed("pkill -f lomiri-music-app")
|
|
|
|
with subtest("lomiri music localisation works"):
|
|
machine.succeed("env LANG=de_DE.UTF-8 lomiri-music-app .mp4 >&2 &")
|
|
machine.wait_for_text("Titel")
|
|
machine.screenshot("lomiri-music_localised")
|
|
'';
|
|
}
|