Unverified Commit 4d232a3a authored by Cosima Neidahl's avatar Cosima Neidahl Committed by GitHub
Browse files

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

parents c124839d fe7d0cd8
Loading
Loading
Loading
Loading
+41 −23
Original line number Diff line number Diff line
@@ -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
@@ -198,7 +199,17 @@ in
        "/share/sounds"
      ];

      systemd.user.services = {
      systemd.user.services =
        let
          lomiriServiceNames = [
            "lomiri.service"
            "lomiri-full-greeter.service"
            "lomiri-full-shell.service"
            "lomiri-greeter.service"
            "lomiri-shell.service"
          ];
        in
        {
          # Unconditionally run service that collects system-installed URL handlers before LUD
          # TODO also run user-installed one?
          "lomiri-url-dispatcher-update-system-dir" = {
@@ -211,23 +222,30 @@ in
            };
          };

        "lomiri-polkit-agent" = rec {
          "lomiri-polkit-agent" = {
            description = "Lomiri Polkit agent";
          wantedBy = [
            "lomiri.service"
            "lomiri-full-greeter.service"
            "lomiri-full-shell.service"
            "lomiri-greeter.service"
            "lomiri-shell.service"
          ];
            wantedBy = lomiriServiceNames;
            after = [ "graphical-session.target" ];
          partOf = wantedBy;
            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 = {
+1 −0
Original line number Diff line number Diff line
@@ -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 {};
+193 −0
Original line number Diff line number Diff line
{ 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")
  '';
}
+124 −0
Original line number Diff line number Diff line
{
  stdenv,
  lib,
  fetchFromGitLab,
  fetchpatch,
  gitUpdater,
  nixosTests,
  cmake,
  gettext,
  gst_all_1,
  libusermetrics,
  lomiri-content-hub,
  lomiri-thumbnailer,
  lomiri-ui-toolkit,
  qtbase,
  qtdeclarative,
  qtmultimedia,
  qtsystems,
  wrapGAppsHook3,
  wrapQtAppsHook,
}:

stdenv.mkDerivation (finalAttrs: {
  pname = "lomiri-music-app";
  version = "3.2.2";

  src = fetchFromGitLab {
    owner = "ubports";
    repo = "development/apps/lomiri-music-app";
    rev = "refs/tags/v${finalAttrs.version}";
    hash = "sha256-tHCbZF+7i/gYs8WqM5jDBhhKmM4ZeUbG3DYBdQAiUT8=";
  };

  patches = [
    # Remove when version > 3.2.2
    (fetchpatch {
      name = "0001-lomiri-music-app-Fix-GNUInstallDirs-usage.patch";
      url = "https://gitlab.com/ubports/development/apps/lomiri-music-app/-/commit/32591f2332aa204b9ee2857992e50594db0e6ff2.patch";
      hash = "sha256-SXn+7jItzi1Q0xK0iK57+W3SpEdSCx1dKSfeghOCePg=";
    })

    # Remove when version > 3.2.2
    (fetchpatch {
      name = "0002-lomiri-music-app-bindtextdomain.patch";
      url = "https://gitlab.com/ubports/development/apps/lomiri-music-app/-/commit/4e950521a67e201f3d02b3b71c6bb1ddce8ef2b2.patch";
      hash = "sha256-HgGKk44FU+IXRVx2NK3iGSo/wPJce1T2k/vP8nZtewQ=";
    })
  ];

  postPatch = ''
    # We don't want absolute paths in desktop files
    substituteInPlace CMakeLists.txt \
      --replace-fail 'ICON ''${DATA_DIR}/''${ICON_FILE}' 'ICON lomiri-music-app' \
      --replace-fail 'SPLASH ''${DATA_DIR}/''${SPLASH_FILE}' 'SPLASH lomiri-app-launch/splash/lomiri-music-app.svg'
  '';

  strictDeps = true;

  nativeBuildInputs = [
    cmake
    gettext
    wrapGAppsHook3
    wrapQtAppsHook
  ];

  buildInputs =
    [
      qtbase
      qtdeclarative

      # QML
      libusermetrics
      lomiri-content-hub
      lomiri-thumbnailer
      lomiri-ui-toolkit
      qtmultimedia
      qtsystems
    ]
    # QtMultimedia playback support
    ++ (with gst_all_1; [
      gstreamer
      gst-plugins-base
      gst-plugins-good
      gst-plugins-bad
    ]);

  dontWrapGApps = true;

  cmakeFlags = [
    (lib.cmakeBool "CLICK_MODE" false)
    (lib.cmakeBool "INSTALL_TESTS" false)
  ];

  # Only autopilot tests
  doCheck = false;

  postInstall = ''
    mkdir -p $out/share/{icons/hicolor/scalable/apps,lomiri-app-launch/splash}

    ln -s $out/share/{lomiri-music-app/app/graphics/music-app.svg,icons/hicolor/scalable/apps/lomiri-music-app.svg}
    ln -s $out/share/{lomiri-music-app/app/graphics/music-app-splash.svg,lomiri-app-launch/splash/lomiri-music-app.svg}
  '';

  preFixup = ''
    qtWrapperArgs+=("''${gappsWrapperArgs[@]}")
  '';

  passthru = {
    tests.vm = nixosTests.lomiri-music-app;
    updateScript = gitUpdater { };
  };

  meta = {
    description = "Default Music application for Ubuntu devices";
    homepage = "https://gitlab.com/ubports/development/apps/lomiri-music-app";
    changelog = "https://gitlab.com/ubports/development/apps/lomiri-music-app/-/blob/v${finalAttrs.version}/ChangeLog";
    license = with lib.licenses; [
      gpl3Only
    ];
    mainProgram = "lomiri-music-app";
    maintainers = lib.teams.lomiri.members;
    platforms = lib.platforms.linux;
  };
})
+5 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@
  makeWrapper,
  pkg-config,
  systemd,
  xdg-user-dirs,
}:

stdenvNoCC.mkDerivation (finalAttrs: {
@@ -34,6 +35,10 @@ stdenvNoCC.mkDerivation (finalAttrs: {

    substituteInPlace systemd/CMakeLists.txt \
      --replace-fail 'pkg_get_variable(SYSTEMD_USER_DIR systemd systemduserunitdir)' 'pkg_get_variable(SYSTEMD_USER_DIR systemd systemduserunitdir DEFINE_VARIABLES prefix=''${CMAKE_INSTALL_PREFIX})'

    # Inject a call to xdg-user-dirs-update, so when mediascanner2 launches, it can actually scan for files
    substituteInPlace desktop/dm-lomiri-session.in \
      --replace-fail '@CMAKE_INSTALL_FULL_LIBEXECDIR@/lomiri-session/run-systemd-session' '${lib.getExe' xdg-user-dirs "xdg-user-dirs-update"} && @CMAKE_INSTALL_FULL_LIBEXECDIR@/lomiri-session/run-systemd-session'
  '';

  nativeBuildInputs = [
Loading