Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lomiri.lomiri-music-app: init at 3.2.2 #364958

Merged
merged 6 commits into from
Feb 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 41 additions & 23 deletions nixos/modules/services/desktop-managers/lomiri.nix
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ in
lomiri-gallery-app
lomiri-history-service
lomiri-mediaplayer-app
lomiri-music-app
lomiri-polkit-agent
lomiri-schemas # exposes some required dbus interfaces
lomiri-session # wrappers to properly launch the session
Expand Down Expand Up @@ -198,37 +199,54 @@ in
"/share/sounds"
];

systemd.user.services = {
# Unconditionally run service that collects system-installed URL handlers before LUD
# TODO also run user-installed one?
"lomiri-url-dispatcher-update-system-dir" = {
description = "Lomiri URL dispatcher system directory updater";
wantedBy = [ "lomiri-url-dispatcher.service" ];
before = [ "lomiri-url-dispatcher.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.lomiri.lomiri-url-dispatcher}/libexec/lomiri-url-dispatcher/lomiri-update-directory /run/current-system/sw/share/lomiri-url-dispatcher/urls/";
};
};

"lomiri-polkit-agent" = rec {
description = "Lomiri Polkit agent";
wantedBy = [
systemd.user.services =
let
lomiriServiceNames = [
"lomiri.service"
"lomiri-full-greeter.service"
"lomiri-full-shell.service"
"lomiri-greeter.service"
"lomiri-shell.service"
];
after = [ "graphical-session.target" ];
partOf = wantedBy;
serviceConfig = {
Type = "simple";
Restart = "always";
ExecStart = "${pkgs.lomiri.lomiri-polkit-agent}/libexec/lomiri-polkit-agent/policykit-agent";
in
{
# Unconditionally run service that collects system-installed URL handlers before LUD
# TODO also run user-installed one?
"lomiri-url-dispatcher-update-system-dir" = {
description = "Lomiri URL dispatcher system directory updater";
wantedBy = [ "lomiri-url-dispatcher.service" ];
before = [ "lomiri-url-dispatcher.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.lomiri.lomiri-url-dispatcher}/libexec/lomiri-url-dispatcher/lomiri-update-directory /run/current-system/sw/share/lomiri-url-dispatcher/urls/";
};
};

"lomiri-polkit-agent" = {
description = "Lomiri Polkit agent";
wantedBy = lomiriServiceNames;
after = [ "graphical-session.target" ];
partOf = lomiriServiceNames;
serviceConfig = {
Type = "simple";
Restart = "always";
ExecStart = "${pkgs.lomiri.lomiri-polkit-agent}/libexec/lomiri-polkit-agent/policykit-agent";
};
};

"mediascanner-2.0" = {
description = "Media Scanner";
wantedBy = lomiriServiceNames;
before = lomiriServiceNames;
partOf = lomiriServiceNames;
serviceConfig = {
Type = "dbus";
BusName = "com.lomiri.MediaScanner2.Daemon";
Restart = "on-failure";
ExecStart = "${lib.getExe pkgs.lomiri.mediascanner2}";
};
};
};
};

systemd.services = {
"dbus-com.lomiri.UserMetrics" = {
Expand Down
1 change: 1 addition & 0 deletions nixos/tests/all-tests.nix
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,7 @@ in {
lomiri-docviewer-app = runTest ./lomiri-docviewer-app.nix;
lomiri-filemanager-app = runTest ./lomiri-filemanager-app.nix;
lomiri-mediaplayer-app = runTest ./lomiri-mediaplayer-app.nix;
lomiri-music-app = runTest ./lomiri-music-app.nix;
lomiri-gallery-app = runTest ./lomiri-gallery-app.nix;
lomiri-system-settings = handleTest ./lomiri-system-settings.nix {};
lorri = handleTest ./lorri/default.nix {};
Expand Down
193 changes: 193 additions & 0 deletions nixos/tests/lomiri-music-app.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,193 @@
{ 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")
'';
}
Loading