2021-10-21 16:40:36 +02:00
|
|
|
{ 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
|
2023-01-24 11:30:04 +01:00
|
|
|
# when cross-compiling. Use the version from buildPackages explicitly to
|
2021-10-21 16:40:36 +02:00
|
|
|
# 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";
|
2022-11-08 22:42:14 +01:00
|
|
|
example = literalExpression
|
|
|
|
"pkgs.kodi.withPackages (exts: [ exts.pvr-iptvsimple ])";
|
2021-10-21 16:40:36 +02:00
|
|
|
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;
|
|
|
|
})
|
|
|
|
]);
|
|
|
|
}
|