Skip to content

Commit

Permalink
AudioVM and client configuration with separate VM audio chennels
Browse files Browse the repository at this point in the history
Signed-off-by: Jon Sahlberg <jon.sahlberg@unikie.com>
  • Loading branch information
josa41 committed Aug 21, 2024
1 parent 565e456 commit 3887d4b
Show file tree
Hide file tree
Showing 8 changed files with 143 additions and 69 deletions.
44 changes: 30 additions & 14 deletions modules/common/services/audio.nix
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
...
}: let
cfg = config.ghaf.services.audio;
inherit (lib) mkIf mkEnableOption mkOption types;
inherit (lib) mkIf mkEnableOption mkOption literalExpression types;
in {
options.ghaf.services.audio = {
enable = mkEnableOption "Enable audio service for audio VM";
Expand All @@ -17,6 +17,17 @@ in {
default = 4713;
description = "TCP port used by Pipewire-pulseaudio service";
};
appStreams = mkOption {
description = "Audio streams for ghaf applications";
type = types.listOf types.str;
default = [];
example = literalExpression ''
[
"chromium"
"element"
]
'';
};
};

config = mkIf cfg.enable {
Expand All @@ -35,27 +46,32 @@ in {
{ name = libpipewire-module-protocol-pulse
args = {
server.address = [
"tcp:4713" # IPv4 and IPv6 on all addresses
{
# Listen TCP port (4713 by default) for IPv4 and IPv6 on all addresses
address = "tcp:0.0.0.0:${toString cfg.pulseaudioTcpPort}"
max-clients = 64
listen-backlog = 32
client.access = "unrestricted"
}
];
pulse.min.req = 128/48000; # 2.7ms
pulse.default.req = 960/48000; # 20 milliseconds
pulse.min.frag = 128/48000; # 2.7ms
pulse.default.frag = 512/48000; # ~10 ms
pulse.default.tlength = 512/48000; # ~10 ms
pulse.min.quantum = 128/48000; # 2.7ms
pulse = {
min.req = 128/48000; # 2.7ms
default.req = 960/48000; # 20 milliseconds
default.tlength = 4800/48000; # 100 ms
# recording buffer options
min.frag = 128/48000; # 2.7ms
default.frag = 960/48000; # 20 ms
# Sheduling
min.quantum = 128/48000; # 2.7ms (test with 1024)
}
}
}
];
'')
];
};

hardware.pulseaudio.extraConfig = ''
# Set sink and source default max volume to about 75% (0-65536)
set-sink-volume @DEFAULT_SINK@ 48000
set-source-volume @DEFAULT_SOURCE@ 48000
'';

# Allow ghaf user to access pulseaudio and pipewire
users.extraUsers.ghaf.extraGroups = ["audio" "video" "pulse-access" "pipewire"];

Expand Down
55 changes: 54 additions & 1 deletion modules/microvm/virtualization/microvm/appvm.nix
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,49 @@
runWaypipe
pkgs.tpm2-tools
pkgs.opensc
];
]
++ (lib.optional (
config.ghaf.profiles.debug.enable )
pkgs.pulseaudio );

# Enable Ghaf audio for Appvm
# TODO maybe make a separate module that can be loaded as per $vm.ghafAudio

sound.enable = vm.ghafAudio;
security.rtkit.enable = vm.ghafAudio;
users.extraUsers.ghaf.extraGroups =
lib.optionals vm.ghafAudio ["audio" "video"];

services.pipewire = lib.mkIf vm.ghafAudio {
enable = true;
pulse.enable = true;

configPackages = [
(pkgs.writeTextDir "share/pipewire/pipewire.conf.d/10-remote-simple.conf" ''
context.modules = [
{
name = libpipewire-module-pulse-tunnel
args = {
tunnel.mode = source
pulse.server.address = "tcp:audio-vm:4713"
reconnect.interval.ms = 500
}
}
{
name = libpipewire-module-pulse-tunnel
args = {
tunnel.mode = sink
pulse.server.address = "tcp:audio-vm:4713"
reconnect.interval.ms = 500
}
}
];
'')
];
};

# config.ghaf.virtualization.microvm.audiovm.appStreams =
# lib.optional (vm.ghafAudio) "${vm.name}";

security.tpm2 = {
enable = true;
Expand Down Expand Up @@ -220,6 +262,11 @@ in {
type = types.nullOr types.str;
default = null;
};
ghafAudio = mkOption {
description = "Enable Ghaf VM Audio support";
type = types.bool;
default = false;
};
vtpm.enable = lib.mkEnableOption "vTPM support in the virtual machine";
};
});
Expand All @@ -234,6 +281,12 @@ in {
default = [];
};

ghafAudio = mkOption {
description = "Enable Ghaf VM Audio support";
type = types.bool;
default = false;
};

# Base VSOCK CID which is used for auto assigning CIDs for all AppVMs
# For example, when it's set to 100, AppVMs will get 100, 101, 102, etc.
# It is also possible to override the auto assinged CID using the vms.cid option
Expand Down
20 changes: 19 additions & 1 deletion modules/microvm/virtualization/microvm/audiovm.nix
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
pkgs,
...
}: let
inherit (lib) mkOption literalExpression types optionals;

configHost = config;
vmName = "audio-vm";
macAddress = "02:00:00:03:03:03";
Expand Down Expand Up @@ -48,14 +50,18 @@
withTimesyncd = true;
withDebug = configHost.ghaf.profiles.debug.enable;
};
services.audio.enable = true;
services.audio = {
enable = true;
appStreams = config.ghaf.virtualization.microvm.audiovm.appStreams;
};
};

environment = {
systemPackages = [
pkgs.pulseaudio
pkgs.pamixer
pkgs.pipewire
pkgs.pw-volume
];
};

Expand Down Expand Up @@ -127,6 +133,18 @@ in {
options.ghaf.virtualization.microvm.audiovm = {
enable = lib.mkEnableOption "AudioVM";

appStreams = lib.mkOption {
description = "Audio streams for ghaf applications";
type = types.listOf types.str;
default = [ "chromium" "element" "business" ];
example = literalExpression ''
[
"chromium"
"element"
]
'';
};

extraModules = lib.mkOption {
description = ''
List of additional modules to be imported and evaluated as part of
Expand Down
1 change: 1 addition & 0 deletions modules/microvm/virtualization/microvm/guivm.nix
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
(rmDesktopEntries [
pkgs.waypipe
pkgs.networkmanagerapplet
pkgs.myxer
])
++ [
pkgs.nm-launcher
Expand Down
19 changes: 1 addition & 18 deletions modules/reference/appvms/business.nix
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ in {
'';
in [
pkgs.chromium
pkgs.pulseaudio
pkgs.xdg-utils
xdgPdfItem
xdgOpenPdf
Expand All @@ -42,23 +41,6 @@ in {
extraModules = [
{
imports = [../programs/chromium.nix];
# Enable pulseaudio for Chromium VM
security.rtkit.enable = true;
sound.enable = true;
users.extraUsers.ghaf.extraGroups = ["audio" "video"];

hardware.pulseaudio = {
enable = true;
extraConfig = ''
load-module module-tunnel-sink sink_name=chromium-speaker server=audio-vm:4713 format=s16le channels=2 rate=48000
load-module module-tunnel-source source_name=chromium-mic server=audio-vm:4713 format=s16le channels=1 rate=48000
# Set sink and source default max volume to about 90% (0-65536)
set-sink-volume chromium-speaker 60000
set-source-volume chromium-mic 60000
'';
};

time.timeZone = config.time.timeZone;

microvm = {
Expand Down Expand Up @@ -246,5 +228,6 @@ in {
}
];
borderColor = "#00FF00";
ghafAudio = true;
vtpm.enable = true;
}
22 changes: 4 additions & 18 deletions modules/reference/appvms/chromium.nix
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ in {
'';
in [
pkgs.chromium
pkgs.pulseaudio
pkgs.xdg-utils
xdgPdfItem
xdgOpenPdf
Expand All @@ -38,23 +37,9 @@ in {
cores = 4;
extraModules = [
{
imports = [../programs/chromium.nix];
# Enable pulseaudio for Chromium VM
security.rtkit.enable = true;
sound.enable = true;
users.extraUsers.ghaf.extraGroups = ["audio" "video"];

hardware.pulseaudio = {
enable = true;
extraConfig = ''
load-module module-tunnel-sink sink_name=chromium-speaker server=audio-vm:4713 format=s16le channels=2 rate=48000
load-module module-tunnel-source source_name=chromium-mic server=audio-vm:4713 format=s16le channels=1 rate=48000
# Set sink and source default max volume to about 90% (0-65536)
set-sink-volume chromium-speaker 60000
set-source-volume chromium-mic 60000
'';
};
imports = [
../programs/chromium.nix
];

time.timeZone = config.time.timeZone;

Expand All @@ -70,5 +55,6 @@ in {
}
];
borderColor = "#630505";
ghafAudio = true;
vtpm.enable = true;
}
18 changes: 1 addition & 17 deletions modules/reference/appvms/element.nix
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,6 @@ in {
cores = 4;
extraModules = [
{
# Enable pulseaudio for user ghaf to access mic
security.rtkit.enable = true;
sound.enable = true;
users.extraUsers.ghaf.extraGroups = ["audio" "video"];

hardware.pulseaudio = {
enable = true;
extraConfig = ''
load-module module-tunnel-sink sink_name=element-speaker server=audio-vm:4713 format=s16le channels=2 rate=48000
load-module module-tunnel-source source_name=element-mic server=audio-vm:4713 format=s16le channels=1 rate=48000
# Set sink and source default max volume to about 90% (0-65536)
set-sink-volume element-speaker 60000
set-source-volume element-mic 60000
'';
};

systemd = {
services = {
element-gps = {
Expand Down Expand Up @@ -97,4 +80,5 @@ in {
}
];
borderColor = "#337aff";
ghafAudio = true;
}
33 changes: 33 additions & 0 deletions modules/reference/services/vm-audio.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Copyright 2022-2024 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0
{
pkgs,
config,
vmName,
...
}: let
speakerName = "${vmName}.speaker";
micName = "${vmName}.mic";
in {
# packages = [
# pkgs.pulseaudio
# pkgs.pamixer
# ];

# Enable pulseaudio for application VM
security.rtkit.enable = true;
sound.enable = true;
users.extraUsers.ghaf.extraGroups = ["audio" "video"];

hardware.pulseaudio = {
enable = true;
extraConfig = "
load-module module-tunnel-sink sink=${speakerName} sink_name=${speakerName} server=audio-vm:4713 format=s16le channels=2 rate=48000
load-module module-tunnel-source source=${micName} source_name=${micName} server=audio-vm:4713 format=s16le channels=1 rate=48000
# Set sink and source default max volume to about 90% (0-65536)
set-sink-volume ${speakerName} 60000
set-source-volume ${micName} 60000
";
};
}

0 comments on commit 3887d4b

Please sign in to comment.