mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-06-25 18:46:32 +03:00

After final improvements to the official formatter implementation,
this commit now performs the first treewide reformat of Nix files using it.
This is part of the implementation of RFC 166.
Only "inactive" files are reformatted, meaning only files that
aren't being touched by any PR with activity in the past 2 months.
This is to avoid conflicts for PRs that might soon be merged.
Later we can do a full treewide reformat to get the rest,
which should not cause as many conflicts.
A CI check has already been running for some time to ensure that new and
already-formatted files are formatted, so the files being reformatted here
should also stay formatted.
This commit was automatically created and can be verified using
nix-build https://github.com/infinisil/treewide-nixpkgs-reformat-script/archive/a08b3a4d199c6124ac5b36a889d9099b4383463f.tar.gz \
--argstr baseRev b32a094368
result/bin/apply-formatting $NIXPKGS_PATH
418 lines
14 KiB
Nix
418 lines
14 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
options,
|
|
pkgs,
|
|
...
|
|
}:
|
|
let
|
|
|
|
gid = config.ids.gids.mediatomb;
|
|
cfg = config.services.mediatomb;
|
|
opt = options.services.mediatomb;
|
|
name = cfg.package.pname;
|
|
pkg = cfg.package;
|
|
optionYesNo = option: if option then "yes" else "no";
|
|
# configuration on media directory
|
|
mediaDirectory = {
|
|
options = {
|
|
path = lib.mkOption {
|
|
type = lib.types.str;
|
|
description = ''
|
|
Absolute directory path to the media directory to index.
|
|
'';
|
|
};
|
|
recursive = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = "Whether the indexation must take place recursively or not.";
|
|
};
|
|
hidden-files = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = "Whether to index the hidden files or not.";
|
|
};
|
|
};
|
|
};
|
|
toMediaDirectory =
|
|
d:
|
|
"<directory location=\"${d.path}\" mode=\"inotify\" recursive=\"${optionYesNo d.recursive}\" hidden-files=\"${optionYesNo d.hidden-files}\" />\n";
|
|
|
|
transcodingConfig =
|
|
if cfg.transcoding then
|
|
with pkgs;
|
|
''
|
|
<transcoding enabled="yes">
|
|
<mimetype-profile-mappings>
|
|
<transcode mimetype="video/x-flv" using="vlcmpeg" />
|
|
<transcode mimetype="application/ogg" using="vlcmpeg" />
|
|
<transcode mimetype="audio/ogg" using="ogg2mp3" />
|
|
</mimetype-profile-mappings>
|
|
<profiles>
|
|
<profile name="ogg2mp3" enabled="no" type="external">
|
|
<mimetype>audio/mpeg</mimetype>
|
|
<accept-url>no</accept-url>
|
|
<first-resource>yes</first-resource>
|
|
<accept-ogg-theora>no</accept-ogg-theora>
|
|
<agent command="${ffmpeg}/bin/ffmpeg" arguments="-y -i %in -f mp3 %out" />
|
|
<buffer size="1048576" chunk-size="131072" fill-size="262144" />
|
|
</profile>
|
|
<profile name="vlcmpeg" enabled="no" type="external">
|
|
<mimetype>video/mpeg</mimetype>
|
|
<accept-url>yes</accept-url>
|
|
<first-resource>yes</first-resource>
|
|
<accept-ogg-theora>yes</accept-ogg-theora>
|
|
<agent command="${lib.getExe vlc}"
|
|
arguments="-I dummy %in --sout #transcode{venc=ffmpeg,vcodec=mp2v,vb=4096,fps=25,aenc=ffmpeg,acodec=mpga,ab=192,samplerate=44100,channels=2}:standard{access=file,mux=ps,dst=%out} vlc:quit" />
|
|
<buffer size="14400000" chunk-size="512000" fill-size="120000" />
|
|
</profile>
|
|
</profiles>
|
|
</transcoding>
|
|
''
|
|
else
|
|
''
|
|
<transcoding enabled="no">
|
|
</transcoding>
|
|
'';
|
|
|
|
configText = lib.optionalString (!cfg.customCfg) ''
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
|
<config version="2" xmlns="http://mediatomb.cc/config/2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://mediatomb.cc/config/2 http://mediatomb.cc/config/2.xsd">
|
|
<server>
|
|
<ui enabled="yes" show-tooltips="yes">
|
|
<accounts enabled="no" session-timeout="30">
|
|
<account user="${name}" password="${name}"/>
|
|
</accounts>
|
|
</ui>
|
|
<name>${cfg.serverName}</name>
|
|
<udn>uuid:${cfg.uuid}</udn>
|
|
<home>${cfg.dataDir}</home>
|
|
<interface>${cfg.interface}</interface>
|
|
<webroot>${pkg}/share/${name}/web</webroot>
|
|
<pc-directory upnp-hide="${optionYesNo cfg.pcDirectoryHide}"/>
|
|
<storage>
|
|
<sqlite3 enabled="yes">
|
|
<database-file>${name}.db</database-file>
|
|
</sqlite3>
|
|
</storage>
|
|
<protocolInfo extend="${optionYesNo cfg.ps3Support}"/>
|
|
${lib.optionalString cfg.dsmSupport ''
|
|
<custom-http-headers>
|
|
<add header="X-User-Agent: redsonic"/>
|
|
</custom-http-headers>
|
|
|
|
<manufacturerURL>redsonic.com</manufacturerURL>
|
|
<modelNumber>105</modelNumber>
|
|
''}
|
|
${lib.optionalString cfg.tg100Support ''
|
|
<upnp-string-limit>101</upnp-string-limit>
|
|
''}
|
|
<extended-runtime-options>
|
|
<mark-played-items enabled="yes" suppress-cds-updates="yes">
|
|
<string mode="prepend">*</string>
|
|
<mark>
|
|
<content>video</content>
|
|
</mark>
|
|
</mark-played-items>
|
|
</extended-runtime-options>
|
|
</server>
|
|
<import hidden-files="no">
|
|
<autoscan use-inotify="auto">
|
|
${lib.concatMapStrings toMediaDirectory cfg.mediaDirectories}
|
|
</autoscan>
|
|
<scripting script-charset="UTF-8">
|
|
<common-script>${pkg}/share/${name}/js/common.js</common-script>
|
|
<playlist-script>${pkg}/share/${name}/js/playlists.js</playlist-script>
|
|
<virtual-layout type="builtin">
|
|
<import-script>${pkg}/share/${name}/js/import.js</import-script>
|
|
</virtual-layout>
|
|
</scripting>
|
|
<mappings>
|
|
<extension-mimetype ignore-unknown="no">
|
|
<map from="mp3" to="audio/mpeg"/>
|
|
<map from="ogx" to="application/ogg"/>
|
|
<map from="ogv" to="video/ogg"/>
|
|
<map from="oga" to="audio/ogg"/>
|
|
<map from="ogg" to="audio/ogg"/>
|
|
<map from="ogm" to="video/ogg"/>
|
|
<map from="asf" to="video/x-ms-asf"/>
|
|
<map from="asx" to="video/x-ms-asf"/>
|
|
<map from="wma" to="audio/x-ms-wma"/>
|
|
<map from="wax" to="audio/x-ms-wax"/>
|
|
<map from="wmv" to="video/x-ms-wmv"/>
|
|
<map from="wvx" to="video/x-ms-wvx"/>
|
|
<map from="wm" to="video/x-ms-wm"/>
|
|
<map from="wmx" to="video/x-ms-wmx"/>
|
|
<map from="m3u" to="audio/x-mpegurl"/>
|
|
<map from="pls" to="audio/x-scpls"/>
|
|
<map from="flv" to="video/x-flv"/>
|
|
<map from="mkv" to="video/x-matroska"/>
|
|
<map from="mka" to="audio/x-matroska"/>
|
|
${lib.optionalString cfg.ps3Support ''
|
|
<map from="avi" to="video/divx"/>
|
|
''}
|
|
${lib.optionalString cfg.dsmSupport ''
|
|
<map from="avi" to="video/avi"/>
|
|
''}
|
|
</extension-mimetype>
|
|
<mimetype-upnpclass>
|
|
<map from="audio/*" to="object.item.audioItem.musicTrack"/>
|
|
<map from="video/*" to="object.item.videoItem"/>
|
|
<map from="image/*" to="object.item.imageItem"/>
|
|
</mimetype-upnpclass>
|
|
<mimetype-contenttype>
|
|
<treat mimetype="audio/mpeg" as="mp3"/>
|
|
<treat mimetype="application/ogg" as="ogg"/>
|
|
<treat mimetype="audio/ogg" as="ogg"/>
|
|
<treat mimetype="audio/x-flac" as="flac"/>
|
|
<treat mimetype="audio/x-ms-wma" as="wma"/>
|
|
<treat mimetype="audio/x-wavpack" as="wv"/>
|
|
<treat mimetype="image/jpeg" as="jpg"/>
|
|
<treat mimetype="audio/x-mpegurl" as="playlist"/>
|
|
<treat mimetype="audio/x-scpls" as="playlist"/>
|
|
<treat mimetype="audio/x-wav" as="pcm"/>
|
|
<treat mimetype="audio/L16" as="pcm"/>
|
|
<treat mimetype="video/x-msvideo" as="avi"/>
|
|
<treat mimetype="video/mp4" as="mp4"/>
|
|
<treat mimetype="audio/mp4" as="mp4"/>
|
|
<treat mimetype="application/x-iso9660" as="dvd"/>
|
|
<treat mimetype="application/x-iso9660-image" as="dvd"/>
|
|
</mimetype-contenttype>
|
|
</mappings>
|
|
<online-content>
|
|
<YouTube enabled="no" refresh="28800" update-at-start="no" purge-after="604800" racy-content="exclude" format="mp4" hd="no">
|
|
<favorites user="${name}"/>
|
|
<standardfeed feed="most_viewed" time-range="today"/>
|
|
<playlists user="${name}"/>
|
|
<uploads user="${name}"/>
|
|
<standardfeed feed="recently_featured" time-range="today"/>
|
|
</YouTube>
|
|
</online-content>
|
|
</import>
|
|
${transcodingConfig}
|
|
</config>
|
|
'';
|
|
defaultFirewallRules = {
|
|
# udp 1900 port needs to be opened for SSDP (not configurable within
|
|
# mediatomb/gerbera) cf.
|
|
# https://docs.gerbera.io/en/latest/run.html?highlight=udp%20port#network-setup
|
|
allowedUDPPorts = [
|
|
1900
|
|
cfg.port
|
|
];
|
|
allowedTCPPorts = [ cfg.port ];
|
|
};
|
|
|
|
in
|
|
{
|
|
|
|
###### interface
|
|
|
|
options = {
|
|
|
|
services.mediatomb = {
|
|
|
|
enable = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Whether to enable the Gerbera/Mediatomb DLNA server.
|
|
'';
|
|
};
|
|
|
|
serverName = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "Gerbera (Mediatomb)";
|
|
description = ''
|
|
How to identify the server on the network.
|
|
'';
|
|
};
|
|
|
|
package = lib.mkPackageOption pkgs "gerbera" { };
|
|
|
|
ps3Support = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Whether to enable ps3 specific tweaks.
|
|
WARNING: incompatible with DSM 320 support.
|
|
'';
|
|
};
|
|
|
|
dsmSupport = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Whether to enable D-Link DSM 320 specific tweaks.
|
|
WARNING: incompatible with ps3 support.
|
|
'';
|
|
};
|
|
|
|
tg100Support = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Whether to enable Telegent TG100 specific tweaks.
|
|
'';
|
|
};
|
|
|
|
transcoding = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Whether to enable transcoding.
|
|
'';
|
|
};
|
|
|
|
dataDir = lib.mkOption {
|
|
type = lib.types.path;
|
|
default = "/var/lib/${name}";
|
|
defaultText = lib.literalExpression ''"/var/lib/''${config.${opt.package}.pname}"'';
|
|
description = ''
|
|
The directory where Gerbera/Mediatomb stores its state, data, etc.
|
|
'';
|
|
};
|
|
|
|
pcDirectoryHide = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = true;
|
|
description = ''
|
|
Whether to list the top-level directory or not (from upnp client standpoint).
|
|
'';
|
|
};
|
|
|
|
user = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "mediatomb";
|
|
description = "User account under which the service runs.";
|
|
};
|
|
|
|
group = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "mediatomb";
|
|
description = "Group account under which the service runs.";
|
|
};
|
|
|
|
port = lib.mkOption {
|
|
type = lib.types.port;
|
|
default = 49152;
|
|
description = ''
|
|
The network port to listen on.
|
|
'';
|
|
};
|
|
|
|
interface = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "";
|
|
description = ''
|
|
A specific interface to bind to.
|
|
'';
|
|
};
|
|
|
|
openFirewall = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
If false (the default), this is up to the user to declare the firewall rules.
|
|
If true, this opens port 1900 (tcp and udp) and the port specified by
|
|
{option}`sercvices.mediatomb.port`.
|
|
|
|
If the option {option}`services.mediatomb.interface` is set,
|
|
the firewall rules opened are dedicated to that interface. Otherwise,
|
|
those rules are opened globally.
|
|
'';
|
|
};
|
|
|
|
uuid = lib.mkOption {
|
|
type = lib.types.str;
|
|
default = "fdfc8a4e-a3ad-4c1d-b43d-a2eedb03a687";
|
|
description = ''
|
|
A unique (on your network) to identify the server by.
|
|
'';
|
|
};
|
|
|
|
mediaDirectories = lib.mkOption {
|
|
type = with lib.types; listOf (submodule mediaDirectory);
|
|
default = [ ];
|
|
description = ''
|
|
Declare media directories to index.
|
|
'';
|
|
example = [
|
|
{
|
|
path = "/data/pictures";
|
|
recursive = false;
|
|
hidden-files = false;
|
|
}
|
|
{
|
|
path = "/data/audio";
|
|
recursive = true;
|
|
hidden-files = false;
|
|
}
|
|
];
|
|
};
|
|
|
|
customCfg = lib.mkOption {
|
|
type = lib.types.bool;
|
|
default = false;
|
|
description = ''
|
|
Allow the service to create and use its own config file inside the `dataDir` as
|
|
configured by {option}`services.mediatomb.dataDir`.
|
|
Deactivated by default, the service then runs with the configuration generated from this module.
|
|
Otherwise, when enabled, no service configuration is generated. Gerbera/Mediatomb then starts using
|
|
config.xml within the configured `dataDir`. It's up to the user to make a correct
|
|
configuration file.
|
|
'';
|
|
};
|
|
|
|
};
|
|
};
|
|
|
|
###### implementation
|
|
|
|
config =
|
|
let
|
|
binaryCommand = "${pkg}/bin/${name}";
|
|
interfaceFlag = lib.optionalString (cfg.interface != "") "--interface ${cfg.interface}";
|
|
configFlag = lib.optionalString (
|
|
!cfg.customCfg
|
|
) "--config ${pkgs.writeText "config.xml" configText}";
|
|
in
|
|
lib.mkIf cfg.enable {
|
|
systemd.services.mediatomb = {
|
|
description = "${cfg.serverName} media Server";
|
|
# Gerbera might fail if the network interface is not available on startup
|
|
# https://github.com/gerbera/gerbera/issues/1324
|
|
wants = [ "network-online.target" ];
|
|
after = [
|
|
"network.target"
|
|
"network-online.target"
|
|
];
|
|
wantedBy = [ "multi-user.target" ];
|
|
serviceConfig.ExecStart = "${binaryCommand} --port ${toString cfg.port} ${interfaceFlag} ${configFlag} --home ${cfg.dataDir}";
|
|
serviceConfig.User = cfg.user;
|
|
serviceConfig.Group = cfg.group;
|
|
};
|
|
|
|
users.groups = lib.optionalAttrs (cfg.group == "mediatomb") {
|
|
mediatomb.gid = gid;
|
|
};
|
|
|
|
users.users = lib.optionalAttrs (cfg.user == "mediatomb") {
|
|
mediatomb = {
|
|
isSystemUser = true;
|
|
group = cfg.group;
|
|
home = cfg.dataDir;
|
|
createHome = true;
|
|
description = "${name} DLNA Server User";
|
|
};
|
|
};
|
|
|
|
# Open firewall only if users enable it
|
|
networking.firewall = lib.mkMerge [
|
|
(lib.mkIf (cfg.openFirewall && cfg.interface != "") {
|
|
interfaces."${cfg.interface}" = defaultFirewallRules;
|
|
})
|
|
(lib.mkIf (cfg.openFirewall && cfg.interface == "") defaultFirewallRules)
|
|
];
|
|
};
|
|
}
|