mirror of
https://github.com/nix-community/home-manager
synced 2024-11-26 21:19:45 +01:00
kodi: add module
Kodi is a media center software.
This commit is contained in:
parent
93b52ce0bd
commit
cbc176010b
13 changed files with 372 additions and 0 deletions
3
.github/CODEOWNERS
vendored
3
.github/CODEOWNERS
vendored
|
@ -114,6 +114,9 @@
|
||||||
|
|
||||||
/modules/programs/keychain.nix @marsam
|
/modules/programs/keychain.nix @marsam
|
||||||
|
|
||||||
|
/modules/programs/kodi.nix @dwagenk
|
||||||
|
/tests/modules/programs/kodi @dwagenk
|
||||||
|
|
||||||
/modules/programs/lazygit.nix @kalhauge
|
/modules/programs/lazygit.nix @kalhauge
|
||||||
|
|
||||||
/modules/programs/less.nix @pamplemousse
|
/modules/programs/less.nix @pamplemousse
|
||||||
|
|
|
@ -19,6 +19,12 @@
|
||||||
github = "CarlosLoboxyz";
|
github = "CarlosLoboxyz";
|
||||||
githubId = 86011416;
|
githubId = 86011416;
|
||||||
};
|
};
|
||||||
|
dwagenk = {
|
||||||
|
email = "dwagenk@mailbox.org";
|
||||||
|
github = "dwagenk";
|
||||||
|
githubId = 32838899;
|
||||||
|
name = "Daniel Wagenknecht";
|
||||||
|
};
|
||||||
justinlovinger = {
|
justinlovinger = {
|
||||||
name = "Justin Lovinger";
|
name = "Justin Lovinger";
|
||||||
email = "git@justinlovinger.com";
|
email = "git@justinlovinger.com";
|
||||||
|
|
|
@ -2387,6 +2387,14 @@ in
|
||||||
A new module is available: 'programs.pandoc'.
|
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'.
|
||||||
|
'';
|
||||||
|
}
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,7 @@ let
|
||||||
./programs/kakoune.nix
|
./programs/kakoune.nix
|
||||||
./programs/keychain.nix
|
./programs/keychain.nix
|
||||||
./programs/kitty.nix
|
./programs/kitty.nix
|
||||||
|
./programs/kodi.nix
|
||||||
./programs/lazygit.nix
|
./programs/lazygit.nix
|
||||||
./programs/less.nix
|
./programs/less.nix
|
||||||
./programs/lesspipe.nix
|
./programs/lesspipe.nix
|
||||||
|
|
255
modules/programs/kodi.nix
Normal file
255
modules/programs/kodi.nix
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
{ config, lib, pkgs, ... }:
|
||||||
|
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.programs.kodi;
|
||||||
|
|
||||||
|
stylesheetCommonHeader = ''
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<xsl:stylesheet xmlns:xsl='http://www.w3.org/1999/XSL/Transform' version='1.0'>
|
||||||
|
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
|
||||||
|
<xsl:strip-space elements="*"/>
|
||||||
|
'';
|
||||||
|
|
||||||
|
stylesheetCommonFooter = "</xsl:stylesheet>";
|
||||||
|
|
||||||
|
stylesheetNestedTags = ''
|
||||||
|
<xsl:template match="attr[attrs]">
|
||||||
|
<xsl:variable name="elementName" select="@name"/>
|
||||||
|
<xsl:element name="{$elementName}">
|
||||||
|
<xsl:apply-templates select="attrs" />
|
||||||
|
</xsl:element>
|
||||||
|
</xsl:template>
|
||||||
|
<xsl:template match="attr[list[attrs]]">
|
||||||
|
<xsl:variable name="elementName" select="@name"/>
|
||||||
|
<xsl:for-each select="list/attrs">
|
||||||
|
<xsl:element name="{$elementName}">
|
||||||
|
<xsl:apply-templates select="." />
|
||||||
|
</xsl:element>
|
||||||
|
</xsl:for-each>
|
||||||
|
</xsl:template>
|
||||||
|
<xsl:template match="attr[not(attrs|list)]">
|
||||||
|
<xsl:variable name="elementName" select="@name"/>
|
||||||
|
<xsl:element name="{$elementName}">
|
||||||
|
<xsl:if test="$elementName='path'">
|
||||||
|
<!-- needed in sources.xml but will be used for all "path" tags -->
|
||||||
|
<xsl:attribute name="pathversion">1</xsl:attribute>
|
||||||
|
</xsl:if>
|
||||||
|
<xsl:value-of select="*/@value" />
|
||||||
|
</xsl:element>
|
||||||
|
</xsl:template>
|
||||||
|
'';
|
||||||
|
|
||||||
|
stylesheetTagsAsSettingWithId = ''
|
||||||
|
<xsl:template match='attr'>
|
||||||
|
<setting>
|
||||||
|
<xsl:attribute name="id">
|
||||||
|
<xsl:value-of select="@name" />
|
||||||
|
</xsl:attribute>
|
||||||
|
<xsl:value-of select="*/@value" />
|
||||||
|
</setting>
|
||||||
|
</xsl:template>
|
||||||
|
'';
|
||||||
|
|
||||||
|
stylesheetAdvancedSettingsRootTag = ''
|
||||||
|
<xsl:template match='/'>
|
||||||
|
<xsl:comment> Generated by Home Manager. </xsl:comment>
|
||||||
|
<advancedsettings version="1.0">
|
||||||
|
<xsl:apply-templates/>
|
||||||
|
</advancedsettings>
|
||||||
|
</xsl:template>
|
||||||
|
'';
|
||||||
|
|
||||||
|
stylesheetSourcesRootTag = ''
|
||||||
|
<xsl:template match='/'>
|
||||||
|
<xsl:comment> Generated by Home Manager. </xsl:comment>
|
||||||
|
<sources>
|
||||||
|
<xsl:apply-templates/>
|
||||||
|
</sources>
|
||||||
|
</xsl:template>
|
||||||
|
'';
|
||||||
|
|
||||||
|
stylesheetAddonSettingsRootTag = ''
|
||||||
|
<xsl:template match='/'>
|
||||||
|
<xsl:comment> Generated by Home Manager. </xsl:comment>
|
||||||
|
<settings version="2">
|
||||||
|
<xsl:apply-templates/>
|
||||||
|
</settings>
|
||||||
|
</xsl:template>
|
||||||
|
'';
|
||||||
|
|
||||||
|
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 <literal>kodi</literal> 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 <literal>advancedsettings.xml</literal>
|
||||||
|
file in kodis userdata directory. Settings specified here will be
|
||||||
|
immutable from inside kodi and be hidden from the GUI settings dialog.
|
||||||
|
</para><para>
|
||||||
|
See <link xlink:href="https://kodi.wiki/view/Advancedsettings.xml"/> as
|
||||||
|
reference for how settings need to be specified.
|
||||||
|
</para><para>
|
||||||
|
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 <literal>sources.xml</literal> in kodis
|
||||||
|
userdata directory.
|
||||||
|
</para><para>
|
||||||
|
See <link xlink:href="https://kodi.wiki/view/Sources.xml"/> as
|
||||||
|
reference for how sources need to be specified.
|
||||||
|
</para><para>
|
||||||
|
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.
|
||||||
|
</para><para>
|
||||||
|
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.
|
||||||
|
</para><para>
|
||||||
|
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;
|
||||||
|
})
|
||||||
|
]);
|
||||||
|
}
|
|
@ -123,6 +123,7 @@ import nmt {
|
||||||
./modules/programs/gnome-terminal
|
./modules/programs/gnome-terminal
|
||||||
./modules/programs/hexchat
|
./modules/programs/hexchat
|
||||||
./modules/programs/i3status-rust
|
./modules/programs/i3status-rust
|
||||||
|
./modules/programs/kodi
|
||||||
./modules/programs/mangohud
|
./modules/programs/mangohud
|
||||||
./modules/programs/ncmpcpp-linux
|
./modules/programs/ncmpcpp-linux
|
||||||
./modules/programs/neovim # Broken package dependency on Darwin.
|
./modules/programs/neovim # Broken package dependency on Darwin.
|
||||||
|
|
5
tests/modules/programs/kodi/default.nix
Normal file
5
tests/modules/programs/kodi/default.nix
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
kodi-example-addon-settings = ./example-addon-settings.nix;
|
||||||
|
kodi-example-settings = ./example-settings.nix;
|
||||||
|
kodi-example-sources = ./example-sources.nix;
|
||||||
|
}
|
|
@ -0,0 +1,4 @@
|
||||||
|
<!-- Generated by Home Manager. -->
|
||||||
|
<settings version="2">
|
||||||
|
<setting id="versioncheck_enable">false</setting>
|
||||||
|
</settings>
|
18
tests/modules/programs/kodi/example-addon-settings.nix
Normal file
18
tests/modules/programs/kodi/example-addon-settings.nix
Normal file
|
@ -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}
|
||||||
|
'';
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
<!-- Generated by Home Manager. -->
|
||||||
|
<advancedsettings version="1.0">
|
||||||
|
<videolibrary>
|
||||||
|
<showemptytvshows>true</showemptytvshows>
|
||||||
|
</videolibrary>
|
||||||
|
</advancedsettings>
|
16
tests/modules/programs/kodi/example-settings.nix
Normal file
16
tests/modules/programs/kodi/example-settings.nix
Normal file
|
@ -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}
|
||||||
|
'';
|
||||||
|
}
|
16
tests/modules/programs/kodi/example-sources-expected.xml
Normal file
16
tests/modules/programs/kodi/example-sources-expected.xml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
<!-- Generated by Home Manager. -->
|
||||||
|
<sources>
|
||||||
|
<video>
|
||||||
|
<default>movies</default>
|
||||||
|
<source>
|
||||||
|
<allowsharing>true</allowsharing>
|
||||||
|
<name>videos</name>
|
||||||
|
<path pathversion="1">/path/to/videos</path>
|
||||||
|
</source>
|
||||||
|
<source>
|
||||||
|
<allowsharing>true</allowsharing>
|
||||||
|
<name>movies</name>
|
||||||
|
<path pathversion="1">/path/to/movies</path>
|
||||||
|
</source>
|
||||||
|
</video>
|
||||||
|
</sources>
|
33
tests/modules/programs/kodi/example-sources.nix
Normal file
33
tests/modules/programs/kodi/example-sources.nix
Normal file
|
@ -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}
|
||||||
|
'';
|
||||||
|
}
|
Loading…
Reference in a new issue