{ 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; }) ]); }