From cbc176010b83361af5eec4b28af78d9fd69a6383 Mon Sep 17 00:00:00 2001 From: Daniel Wagenknecht Date: Thu, 21 Oct 2021 16:40:36 +0200 Subject: [PATCH] kodi: add module Kodi is a media center software. --- .github/CODEOWNERS | 3 + modules/lib/maintainers.nix | 6 + modules/misc/news.nix | 8 + modules/modules.nix | 1 + modules/programs/kodi.nix | 255 ++++++++++++++++++ tests/default.nix | 1 + tests/modules/programs/kodi/default.nix | 5 + .../kodi/example-addon-settings-expected.xml | 4 + .../programs/kodi/example-addon-settings.nix | 18 ++ .../kodi/example-settings-expected.xml | 6 + .../programs/kodi/example-settings.nix | 16 ++ .../kodi/example-sources-expected.xml | 16 ++ .../modules/programs/kodi/example-sources.nix | 33 +++ 13 files changed, 372 insertions(+) create mode 100644 modules/programs/kodi.nix create mode 100644 tests/modules/programs/kodi/default.nix create mode 100644 tests/modules/programs/kodi/example-addon-settings-expected.xml create mode 100644 tests/modules/programs/kodi/example-addon-settings.nix create mode 100644 tests/modules/programs/kodi/example-settings-expected.xml create mode 100644 tests/modules/programs/kodi/example-settings.nix create mode 100644 tests/modules/programs/kodi/example-sources-expected.xml create mode 100644 tests/modules/programs/kodi/example-sources.nix diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 5d3fea78d..ade521900 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -114,6 +114,9 @@ /modules/programs/keychain.nix @marsam +/modules/programs/kodi.nix @dwagenk +/tests/modules/programs/kodi @dwagenk + /modules/programs/lazygit.nix @kalhauge /modules/programs/less.nix @pamplemousse diff --git a/modules/lib/maintainers.nix b/modules/lib/maintainers.nix index 0eb348299..0a54d1e02 100644 --- a/modules/lib/maintainers.nix +++ b/modules/lib/maintainers.nix @@ -19,6 +19,12 @@ github = "CarlosLoboxyz"; githubId = 86011416; }; + dwagenk = { + email = "dwagenk@mailbox.org"; + github = "dwagenk"; + githubId = 32838899; + name = "Daniel Wagenknecht"; + }; justinlovinger = { name = "Justin Lovinger"; email = "git@justinlovinger.com"; diff --git a/modules/misc/news.nix b/modules/misc/news.nix index 94c053b81..b5678546f 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -2387,6 +2387,14 @@ in A new module is available: 'programs.pandoc'. ''; } + + { + time = "2022-01-26T22:08:29+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'programs.kodi'. + ''; + } ]; }; } diff --git a/modules/modules.nix b/modules/modules.nix index 42b3e902f..844a62ad7 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -86,6 +86,7 @@ let ./programs/kakoune.nix ./programs/keychain.nix ./programs/kitty.nix + ./programs/kodi.nix ./programs/lazygit.nix ./programs/less.nix ./programs/lesspipe.nix diff --git a/modules/programs/kodi.nix b/modules/programs/kodi.nix new file mode 100644 index 000000000..361699481 --- /dev/null +++ b/modules/programs/kodi.nix @@ -0,0 +1,255 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.programs.kodi; + + stylesheetCommonHeader = '' + + + + + ''; + + stylesheetCommonFooter = ""; + + stylesheetNestedTags = '' + + + + + + + + + + + + + + + + + + + + 1 + + + + + ''; + + stylesheetTagsAsSettingWithId = '' + + + + + + + + + ''; + + stylesheetAdvancedSettingsRootTag = '' + + Generated by Home Manager. + + + + + ''; + + stylesheetSourcesRootTag = '' + + Generated by Home Manager. + + + + + ''; + + stylesheetAddonSettingsRootTag = '' + + Generated by Home Manager. + + + + + ''; + + attrsetToXml = attrs: name: stylesheet: + pkgs.runCommand name { + # Package splicing for libxslt does not work correctly leading to errors + # when cross-compiling. Use the version from buildPackages explicitely to + # fix this. + nativeBuildInputs = [ pkgs.buildPackages.libxslt.bin ]; + xml = builtins.toXML attrs; + passAsFile = [ "xml" ]; + } '' + xsltproc ${stylesheet} - < "$xmlPath" > "$out" + ''; + + attrsetToAdvancedSettingsXml = attrs: name: + let + stylesheet = builtins.toFile "stylesheet.xsl" '' + ${stylesheetCommonHeader} + ${stylesheetAdvancedSettingsRootTag} + ${stylesheetNestedTags} + ${stylesheetCommonFooter} + ''; + in attrsetToXml attrs name stylesheet; + + attrsetToSourcesXml = attrs: name: + let + stylesheet = builtins.toFile "stylesheet.xsl" '' + ${stylesheetCommonHeader} + ${stylesheetSourcesRootTag} + ${stylesheetNestedTags} + ${stylesheetCommonFooter} + ''; + in attrsetToXml attrs name stylesheet; + + attrsetToAddonSettingsXml = attrs: name: + let + stylesheet = builtins.toFile "stylesheet.xsl" '' + ${stylesheetCommonHeader} + ${stylesheetAddonSettingsRootTag} + ${stylesheetTagsAsSettingWithId} + ${stylesheetCommonFooter} + ''; + in attrsetToXml attrs name stylesheet; + +in { + meta.maintainers = [ hm.maintainers.dwagenk ]; + + options.programs.kodi = { + enable = mkEnableOption "Kodi"; + + package = mkOption { + type = types.package; + default = pkgs.kodi; + defaultText = literalExpression "pkgs.kodi"; + example = literalExpression '' + { pkgs.kodi.withPackages (exts: [ exts.pvr-iptvsimple ]) } + ''; + description = '' + The kodi package to use. + Can be used to specify extensions. + ''; + }; + + datadir = mkOption { + type = types.path; + default = "${config.home.homeDirectory}/.kodi"; + defaultText = + literalExpression ''"''${config.home.homeDirectory}/.kodi"''; + example = literalExpression ''"''${config.xdg.dataHome}/kodi"''; + description = "Directory to store configuration and metadata."; + }; + + settings = mkOption { + type = with types; + let + valueType = either str (attrsOf valueType) // { + description = "attribute sets of strings"; + }; + in nullOr valueType; + default = null; + example = literalExpression '' + { videolibrary.showemptytvshows = "true"; } + ''; + description = '' + Configuration to write to the advancedsettings.xml + file in kodis userdata directory. Settings specified here will be + immutable from inside kodi and be hidden from the GUI settings dialog. + + See as + reference for how settings need to be specified. + + The innermost attributes must be of type str. + ''; + }; + + sources = mkOption { + type = with types; + let + valueType = oneOf [ str (attrsOf valueType) (listOf valueType) ] // { + description = "attribute sets or lists of strings"; + }; + in nullOr valueType; + default = null; + example = literalExpression '' + { + video = { + default = "movies"; + source = [ + { name = "videos"; path = "/path/to/videos"; allowsharing = "true"; } + { name = "movies"; path = "/path/to/movies"; allowsharing = "true"; } + ]; + }; + } + ''; + description = '' + Contents to populate the file sources.xml in kodis + userdata directory. + + See as + reference for how sources need to be specified. + + Kodi will still show the dialogs to modify sources in the GUI and they + appear to be mutable. This however is not the case and the sources will + stay as specified via Home Manager. + + The innermost attributes must be of type str. + ''; + }; + + addonSettings = mkOption { + type = with types; nullOr (attrsOf (attrsOf str)); + default = null; + example = literalExpression '' + { "service.xbmc.versioncheck".versioncheck_enable = "false"; } + ''; + description = '' + Attribute set with the plugin namespace as toplevel key and the plugins + settings as lower level key/value pairs. + + Kodi will still show the settings of plugins configured via this + mechanism in the GUI and they appear to be mutable. This however is + not the case and the settings will stay as specified via Home Manager. + ''; + }; + }; + + config = mkIf cfg.enable (mkMerge [ + { + assertions = [ + (lib.hm.assertions.assertPlatform "programs.kodi" pkgs + lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + home.sessionVariables = { KODI_DATA = cfg.datadir; }; + } + + (mkIf (cfg.settings != null) { + home.file."${cfg.datadir}/userdata/advancedsettings.xml".source = + attrsetToAdvancedSettingsXml cfg.settings "kodi-advancedsettings.xml"; + }) + + (mkIf (cfg.sources != null) { + home.file."${cfg.datadir}/userdata/sources.xml".source = + attrsetToSourcesXml cfg.sources "kodi-sources.xml"; + }) + + (mkIf (cfg.addonSettings != null) { + home.file = mapAttrs' (k: v: + attrsets.nameValuePair + ("${cfg.datadir}/userdata/addon_data/${k}/settings.xml") { + source = attrsetToAddonSettingsXml v "kodi-addon-${k}-settings.xml"; + }) cfg.addonSettings; + }) + ]); +} diff --git a/tests/default.nix b/tests/default.nix index 6844f6735..3a2eb4ffc 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -123,6 +123,7 @@ import nmt { ./modules/programs/gnome-terminal ./modules/programs/hexchat ./modules/programs/i3status-rust + ./modules/programs/kodi ./modules/programs/mangohud ./modules/programs/ncmpcpp-linux ./modules/programs/neovim # Broken package dependency on Darwin. diff --git a/tests/modules/programs/kodi/default.nix b/tests/modules/programs/kodi/default.nix new file mode 100644 index 000000000..1902645c4 --- /dev/null +++ b/tests/modules/programs/kodi/default.nix @@ -0,0 +1,5 @@ +{ + kodi-example-addon-settings = ./example-addon-settings.nix; + kodi-example-settings = ./example-settings.nix; + kodi-example-sources = ./example-sources.nix; +} diff --git a/tests/modules/programs/kodi/example-addon-settings-expected.xml b/tests/modules/programs/kodi/example-addon-settings-expected.xml new file mode 100644 index 000000000..21259b244 --- /dev/null +++ b/tests/modules/programs/kodi/example-addon-settings-expected.xml @@ -0,0 +1,4 @@ + + + false + diff --git a/tests/modules/programs/kodi/example-addon-settings.nix b/tests/modules/programs/kodi/example-addon-settings.nix new file mode 100644 index 000000000..c591d1ae3 --- /dev/null +++ b/tests/modules/programs/kodi/example-addon-settings.nix @@ -0,0 +1,18 @@ +{ config, ... }: + +{ + programs.kodi = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + addonSettings = { + "service.xbmc.versioncheck".versioncheck_enable = "false"; + }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.kodi/userdata/addon_data/service.xbmc.versioncheck/settings.xml \ + ${./example-addon-settings-expected.xml} + ''; +} diff --git a/tests/modules/programs/kodi/example-settings-expected.xml b/tests/modules/programs/kodi/example-settings-expected.xml new file mode 100644 index 000000000..2aca97637 --- /dev/null +++ b/tests/modules/programs/kodi/example-settings-expected.xml @@ -0,0 +1,6 @@ + + + + true + + diff --git a/tests/modules/programs/kodi/example-settings.nix b/tests/modules/programs/kodi/example-settings.nix new file mode 100644 index 000000000..bdb48268a --- /dev/null +++ b/tests/modules/programs/kodi/example-settings.nix @@ -0,0 +1,16 @@ +{ config, ... }: + +{ + programs.kodi = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + settings = { videolibrary.showemptytvshows = "true"; }; + }; + + nmt.script = '' + assertFileContent \ + home-files/.kodi/userdata/advancedsettings.xml \ + ${./example-settings-expected.xml} + ''; +} diff --git a/tests/modules/programs/kodi/example-sources-expected.xml b/tests/modules/programs/kodi/example-sources-expected.xml new file mode 100644 index 000000000..736f8963a --- /dev/null +++ b/tests/modules/programs/kodi/example-sources-expected.xml @@ -0,0 +1,16 @@ + + + + diff --git a/tests/modules/programs/kodi/example-sources.nix b/tests/modules/programs/kodi/example-sources.nix new file mode 100644 index 000000000..f49b50001 --- /dev/null +++ b/tests/modules/programs/kodi/example-sources.nix @@ -0,0 +1,33 @@ +{ config, ... }: + +{ + programs.kodi = { + enable = true; + package = config.lib.test.mkStubPackage { }; + + sources = { + video = { + default = "movies"; + source = [ + { + name = "videos"; + path = "/path/to/videos"; + allowsharing = "true"; + } + { + name = "movies"; + path = "/path/to/movies"; + allowsharing = "true"; + } + ]; + }; + }; + + }; + + nmt.script = '' + assertFileContent \ + home-files/.kodi/userdata/sources.xml \ + ${./example-sources-expected.xml} + ''; +}