diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index a7a31ba85768..a6839e02c4fc 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -348,6 +348,7 @@ in #mailman = 316; # removed 2019-08-30 zigbee2mqtt = 317; # shadow = 318; # unused + hqplayer = 319; # When adding a uid, make sure it doesn't match an existing gid. And don't use uids above 399! @@ -650,6 +651,7 @@ in #mailman = 316; # removed 2019-08-30 zigbee2mqtt = 317; shadow = 318; + hqplayer = 319; # When adding a gid, make sure it doesn't match an existing # uid. Users and groups with the same name should have equal diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 4203c858272f..64b0c83bbae9 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -244,8 +244,9 @@ ./services/amqp/rabbitmq.nix ./services/audio/alsa.nix ./services/audio/botamusique.nix - ./services/audio/jack.nix + ./services/audio/hqplayerd.nix ./services/audio/icecast.nix + ./services/audio/jack.nix ./services/audio/jmusicbot.nix ./services/audio/liquidsoap.nix ./services/audio/mpd.nix diff --git a/nixos/modules/services/audio/hqplayerd.nix b/nixos/modules/services/audio/hqplayerd.nix new file mode 100644 index 000000000000..3a703c97c0f7 --- /dev/null +++ b/nixos/modules/services/audio/hqplayerd.nix @@ -0,0 +1,166 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + cfg = config.services.hqplayerd; + pkg = pkgs.hqplayerd; + # XXX: This is hard-coded in the distributed binary, don't try to change it. + stateDir = "/var/lib/hqplayer"; + configDir = "/etc/hqplayer"; +in +{ + options = { + services.hqplayerd = { + enable = mkEnableOption "HQPlayer Embedded"; + + licenseFile = mkOption { + type = types.nullOr types.path; + default = null; + description = '' + Path to the HQPlayer license key file. + + Without this, the service will run in trial mode and restart every 30 + minutes. + ''; + }; + + auth = { + username = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Username used for HQPlayer's WebUI. + + Without this you will need to manually create the credentials after + first start by going to http://your.ip/8088/auth + ''; + }; + + password = mkOption { + type = types.nullOr types.str; + default = null; + description = '' + Password used for HQPlayer's WebUI. + + Without this you will need to manually create the credentials after + first start by going to http://your.ip/8088/auth + ''; + }; + }; + + openFirewall = mkOption { + type = types.bool; + default = false; + description = '' + Open TCP port 8088 in the firewall for the server. + ''; + }; + + user = mkOption { + type = types.str; + default = "hqplayer"; + description = '' + User account under which hqplayerd runs. + ''; + }; + + group = mkOption { + type = types.str; + default = "hqplayer"; + description = '' + Group account under which hqplayerd runs. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + { + assertion = (cfg.auth.username != null -> cfg.auth.password != null) + && (cfg.auth.password != null -> cfg.auth.username != null); + message = "You must set either both services.hqplayer.auth.username and password, or neither."; + } + ]; + + environment = { + etc = { + "hqplayer/hqplayerd4-key.xml" = mkIf (cfg.licenseFile != null) { source = cfg.licenseFile; }; + "modules-load.d/taudio2.conf".source = "${pkg}/etc/modules-load.d/taudio2.conf"; + }; + systemPackages = [ pkg ]; + }; + + networking.firewall = mkIf cfg.openFirewall { + allowedTCPPorts = [ 8088 ]; + }; + + services.udev.packages = [ pkg ]; + + systemd = { + tmpfiles.rules = [ + "d ${configDir} 0755 ${cfg.user} ${cfg.group} - -" + "d ${stateDir} 0755 ${cfg.user} ${cfg.group} - -" + ]; + + services.hqplayerd = { + description = "HQPlayer daemon"; + wantedBy = [ "multi-user.target" ]; + requires = [ "network-online.target" "sound.target" "systemd-udev-settle.service" ]; + after = [ "network-online.target" "sound.target" "systemd-udev-settle.service" "local-fs.target" "remote-fs.target" "systemd-tmpfiles-setup.service" ]; + + unitConfig.ConditionPathExists = [ configDir stateDir ]; + + preStart = + let + blankCfg = pkgs.writeText "hqplayerd.xml" '' + + + + ''; + in + '' + cp -r "${pkg}/var/lib/hqplayer/web" "${stateDir}" + chmod -R u+wX "${stateDir}/web" + + if [ ! -f "${configDir}/hqplayerd.xml" ]; then + echo "creating blank config file" + install -m 0644 "${blankCfg}" "${configDir}/hqplayerd.xml" + fi + '' + optionalString (cfg.auth.username != null && cfg.auth.password != null) '' + ${pkg}/bin/hqplayerd -s ${cfg.auth.username} ${cfg.auth.password} + ''; + + serviceConfig = { + ExecStart = "${pkg}/bin/hqplayerd"; + + User = cfg.user; + Group = cfg.group; + + Restart = "on-failure"; + RestartSec = 5; + + Nice = -10; + IOSchedulingClass = "realtime"; + LimitMEMLOCK = "1G"; + LimitNICE = -10; + LimitRTPRIO = 98; + }; + }; + }; + + users.groups = mkIf (cfg.group == "hqplayer") { + hqplayer.gid = config.ids.gids.hqplayer; + }; + + users.users = mkIf (cfg.user == "hqplayer") { + hqplayer = { + description = "hqplayer daemon user"; + extraGroups = [ "audio" ]; + group = cfg.group; + uid = config.ids.uids.hqplayer; + }; + }; + }; +} diff --git a/pkgs/applications/networking/browsers/chromium/update.py b/pkgs/applications/networking/browsers/chromium/update.py index d6788fa41927..4f9f53bd02ac 100755 --- a/pkgs/applications/networking/browsers/chromium/update.py +++ b/pkgs/applications/networking/browsers/chromium/update.py @@ -3,6 +3,7 @@ """This script automatically updates chromium, google-chrome, chromedriver, and ungoogled-chromium via upstream-info.json.""" +# Usage: ./update.py [--commit] import csv import json @@ -22,6 +23,7 @@ DEB_URL = 'https://dl.google.com/linux/chrome/deb/pool/main/g' BUCKET_URL = 'https://commondatastorage.googleapis.com/chromium-browser-official' JSON_PATH = dirname(abspath(__file__)) + '/upstream-info.json' +COMMIT_MESSAGE_SCRIPT = dirname(abspath(__file__)) + '/get-commit-message.py' def load_json(path): @@ -117,6 +119,21 @@ def channel_name_to_attr_name(channel_name): sys.exit(1) +def get_channel_key(item): + """Orders Chromium channels by their name.""" + channel_name = item[0] + if channel_name == 'stable': + return 0 + if channel_name == 'beta': + return 1 + if channel_name == 'dev': + return 2 + if channel_name == 'ungoogled-chromium': + return 3 + print(f'Error: Unexpected channel: {channel_name}', file=sys.stderr) + sys.exit(1) + + def print_updates(channels_old, channels_new): """Print a summary of the updates.""" print('Updates:') @@ -192,21 +209,31 @@ with urlopen(HISTORY_URL) as resp: channels[channel_name] = channel -with open(JSON_PATH, 'w') as out: - def get_channel_key(item): - """Orders Chromium channels by their name.""" - channel_name = item[0] - if channel_name == 'stable': - return 0 - if channel_name == 'beta': - return 1 - if channel_name == 'dev': - return 2 - if channel_name == 'ungoogled-chromium': - return 3 - print(f'Error: Unexpected channel: {channel_name}', file=sys.stderr) - sys.exit(1) - sorted_channels = OrderedDict(sorted(channels.items(), key=get_channel_key)) - json.dump(sorted_channels, out, indent=2) - out.write('\n') +sorted_channels = OrderedDict(sorted(channels.items(), key=get_channel_key)) +if len(sys.argv) == 2 and sys.argv[1] == '--commit': + for channel_name in sorted_channels.keys(): + version_old = last_channels[channel_name]['version'] + version_new = sorted_channels[channel_name]['version'] + if LooseVersion(version_old) < LooseVersion(version_new): + last_channels[channel_name] = sorted_channels[channel_name] + with open(JSON_PATH, 'w') as out: + json.dump(last_channels, out, indent=2) + out.write('\n') + attr_name = channel_name_to_attr_name(channel_name) + commit_message = f'{attr_name}: {version_old} -> {version_new}' + if channel_name == 'stable': + body = subprocess.check_output([COMMIT_MESSAGE_SCRIPT]).decode('utf-8') + prefix = f'chromium: TODO -> {version_new}' + if not body.startswith(prefix): + print("Error: Couldn't fetch the the release notes for the following update:") + print(commit_message) + sys.exit(1) + body = body.removeprefix(prefix) + commit_message += body + subprocess.run(['git', 'add', JSON_PATH], check=True) + subprocess.run(['git', 'commit', '--file=-'], input=commit_message.encode(), check=True) +else: + with open(JSON_PATH, 'w') as out: + json.dump(sorted_channels, out, indent=2) + out.write('\n') print_updates(last_channels, sorted_channels) diff --git a/pkgs/applications/networking/browsers/chromium/upstream-info.json b/pkgs/applications/networking/browsers/chromium/upstream-info.json index a0a8fd23e6bc..1066d322bad0 100644 --- a/pkgs/applications/networking/browsers/chromium/upstream-info.json +++ b/pkgs/applications/networking/browsers/chromium/upstream-info.json @@ -31,15 +31,15 @@ } }, "dev": { - "version": "93.0.4577.18", - "sha256": "1h1ppyizj5vbnrv11iy9vlcpcv8mgb9r8m2zmz6vp7q1ch6w0w4x", - "sha256bin64": "14cw0k4gsilybg7gbbbmck62i0prq5rm6hwqalmmmiqcldrw05mq", + "version": "94.0.4595.0", + "sha256": "0ksd7vqpbiplbg2xpm566z7p7qp57r27a3pk6ss1qz8v18490092", + "sha256bin64": "1kibyhgwcgby3hnhjdg2vrgbj4dvvbicqlcj4id9761zw1jhz8r4", "deps": { "gn": { - "version": "2021-07-08", + "version": "2021-07-31", "url": "https://gn.googlesource.com/gn", - "rev": "24e2f7df92641de0351a96096fb2c490b2436bb8", - "sha256": "1lwkyhfhw0zd7daqz466n7x5cddf0danr799h4jg3s0yvd4galjl" + "rev": "eea3906f0e2a8d3622080127d2005ff214d51383", + "sha256": "1wc969jrivb502c45wdcbgh0c5888nqxla05is9bimkrk9rqppw3" } } }, diff --git a/pkgs/servers/hqplayerd/default.nix b/pkgs/servers/hqplayerd/default.nix index 594085d422ef..76f8bde3e4ed 100644 --- a/pkgs/servers/hqplayerd/default.nix +++ b/pkgs/servers/hqplayerd/default.nix @@ -17,11 +17,11 @@ stdenv.mkDerivation rec { pname = "hqplayerd"; - version = "4.24.2-63"; + version = "4.25.0-64"; src = fetchurl { url = "https://www.signalyst.eu/bins/${pname}/fc34/${pname}-${version}.fc34.x86_64.rpm"; - sha256 = "sha256-6JUgHDO+S73n/IVQhkmC0Nw4GQVzTLtiBbz/wZiflRg="; + sha256 = "sha256-KLP7g1SQzVKu9Hnptb6s0FwmLSjhlAINJoJskja+bDM="; }; unpackPhase = '' @@ -70,8 +70,8 @@ stdenv.mkDerivation rec { cp ./usr/share/doc/hqplayerd/* $out/share/doc/hqplayerd # misc service support files - mkdir -p $out/var/lib/hqplayerd - cp -r ./var/lib/hqplayer/web $out/var/lib/hqplayer + mkdir -p $out/var/lib/hqplayer + cp -r ./var/lib/hqplayer/web $out/var/lib/hqplayer/web runHook postInstall '';