mirror of
https://github.com/Theaninova/TheaninovOS.git
synced 2026-07-25 01:54:48 +00:00
feat: audio cast
This commit is contained in:
@@ -67,7 +67,17 @@
|
|||||||
|
|
||||||
hardware = {
|
hardware = {
|
||||||
amdgpu.preset.default.enable = true;
|
amdgpu.preset.default.enable = true;
|
||||||
audio.preset.pipewire.enable = true;
|
audio = {
|
||||||
|
preset.pipewire.enable = true;
|
||||||
|
audio-share = {
|
||||||
|
enable = true;
|
||||||
|
partner = {
|
||||||
|
ip = "192.168.0.51";
|
||||||
|
name = "Luci";
|
||||||
|
combine = "astro-a50-eq-harman-in";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
cc1.enable = true;
|
cc1.enable = true;
|
||||||
fv43u.enable = true;
|
fv43u.enable = true;
|
||||||
astro-a50.enable = true;
|
astro-a50.enable = true;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
extraConfig.PROJECTS = "${config.home.homeDirectory}/Projects";
|
extraConfig.PROJECTS = "${config.home.homeDirectory}/Projects";
|
||||||
};
|
};
|
||||||
programs.zoxide.enable = true;
|
programs.zoxide.enable = true;
|
||||||
|
services.jellyfin-mpv-shim.enable = true;
|
||||||
wayland.windowManager.hyprland.settings.device =
|
wayland.windowManager.hyprland.settings.device =
|
||||||
let
|
let
|
||||||
targetDPI = 1200;
|
targetDPI = 1200;
|
||||||
|
|||||||
+7
-1
@@ -13,6 +13,12 @@
|
|||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
blueman
|
blueman
|
||||||
kdePackages.okular
|
kdePackages.okular
|
||||||
|
(pkgs.writeShellApplication {
|
||||||
|
name = "shut";
|
||||||
|
text = ''
|
||||||
|
shutdown now
|
||||||
|
'';
|
||||||
|
})
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
wayland.windowManager.hyprland.settings = {
|
wayland.windowManager.hyprland.settings = {
|
||||||
@@ -23,7 +29,7 @@
|
|||||||
mfact = 0.65;
|
mfact = 0.65;
|
||||||
always_keep_position = true;
|
always_keep_position = true;
|
||||||
};
|
};
|
||||||
input.kb_options = [ "lv3:caps_switch" ];
|
input.kb_options = "lv3:caps_switch";
|
||||||
};
|
};
|
||||||
monitor = [
|
monitor = [
|
||||||
{
|
{
|
||||||
|
|||||||
+11
-1
@@ -72,7 +72,17 @@
|
|||||||
|
|
||||||
hardware = {
|
hardware = {
|
||||||
q3279vwf.enable = true;
|
q3279vwf.enable = true;
|
||||||
audio.preset.pipewire.enable = true;
|
audio = {
|
||||||
|
preset.pipewire.enable = true;
|
||||||
|
audio-share = {
|
||||||
|
enable = true;
|
||||||
|
partner = {
|
||||||
|
ip = "192.168.0.84";
|
||||||
|
name = "Thea";
|
||||||
|
combine = "alsa_output.usb-SteelSeries_Arctis_Pro_Wireless-00.pro-output-0";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
cc1.enable = true;
|
cc1.enable = true;
|
||||||
|
|
||||||
nvidia.preset.proprietary.enable = true;
|
nvidia.preset.proprietary.enable = true;
|
||||||
|
|||||||
@@ -15,9 +15,15 @@
|
|||||||
kdePackages.okular
|
kdePackages.okular
|
||||||
bitbox
|
bitbox
|
||||||
gamma-launcher
|
gamma-launcher
|
||||||
|
(pkgs.writeShellApplication {
|
||||||
|
name = "shut";
|
||||||
|
text = ''
|
||||||
|
shutdown now
|
||||||
|
'';
|
||||||
|
})
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
wayland.windowManager.hyprland.settings.config.input.kb_options = [ "lv3:caps_switch" ];
|
wayland.windowManager.hyprland.settings.config.input.kb_options = "lv3:caps_switch";
|
||||||
services.nextcloud-client.enable = true;
|
services.nextcloud-client.enable = true;
|
||||||
systemd.user.services = {
|
systemd.user.services = {
|
||||||
nm-applet = {
|
nm-applet = {
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
tone-mapping = "mobius";
|
tone-mapping = "mobius";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
services.jellyfin-mpv-shim.enable = true;
|
|
||||||
home.packages = with pkgs; [
|
home.packages = with pkgs; [
|
||||||
# nix
|
# nix
|
||||||
cachix
|
cachix
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
./fonts/nerd-fonts.nix
|
./fonts/nerd-fonts.nix
|
||||||
./fonts/open-dyslexic.nix
|
./fonts/open-dyslexic.nix
|
||||||
|
|
||||||
|
./hardware/audio-share.nix
|
||||||
./hardware/astro-a50.nix
|
./hardware/astro-a50.nix
|
||||||
./hardware/audio.nix
|
./hardware/audio.nix
|
||||||
./hardware/gbmonctl.nix
|
./hardware/gbmonctl.nix
|
||||||
|
|||||||
@@ -0,0 +1,157 @@
|
|||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
username,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib;
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.hardware.audio.audio-share;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.hardware.audio.audio-share = {
|
||||||
|
enable = mkEnableOption "LAN Audio Sharing";
|
||||||
|
partner = mkOption {
|
||||||
|
type = types.submodule {
|
||||||
|
options = {
|
||||||
|
ip = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "The IP address of the partner machine to share audio with.";
|
||||||
|
};
|
||||||
|
name = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "Name of the partner machine (for display purposes)";
|
||||||
|
};
|
||||||
|
combine = mkOption {
|
||||||
|
type = types.str;
|
||||||
|
description = "Name of the sink to combine the shared output with";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config =
|
||||||
|
let
|
||||||
|
sourcePort = 10001;
|
||||||
|
repairPort = 10002;
|
||||||
|
controlPort = 10003;
|
||||||
|
sinkName = "combined_output_3";
|
||||||
|
in
|
||||||
|
mkIf cfg.enable {
|
||||||
|
networking.firewall.allowedUDPPorts = [
|
||||||
|
sourcePort
|
||||||
|
repairPort
|
||||||
|
controlPort
|
||||||
|
];
|
||||||
|
home-manager.users.${username} = {
|
||||||
|
programs.waybar.settings.mainBar = {
|
||||||
|
"pulseaudio" = {
|
||||||
|
format-icons.${sinkName} = "";
|
||||||
|
on-click-right = lib.getExe (
|
||||||
|
pkgs.writeShellApplication {
|
||||||
|
name = "toggle-audio-share";
|
||||||
|
runtimeEnv = {
|
||||||
|
SINK_A = sinkName;
|
||||||
|
SINK_B = cfg.partner.combine;
|
||||||
|
};
|
||||||
|
text = builtins.readFile ./audio-share.sh;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
xdg.configFile = {
|
||||||
|
"pipewire/pipewire.conf.d/52-audio-share.conf".text = builtins.toJSON {
|
||||||
|
"context.modules" = [
|
||||||
|
{
|
||||||
|
name = "libpipewire-module-roc-source";
|
||||||
|
args = {
|
||||||
|
"local.ip" = "0.0.0.0";
|
||||||
|
"roc.resampler.backend" = "default";
|
||||||
|
"roc.resampler.profile" = "default";
|
||||||
|
"roc.latency-tuner.backend" = "default";
|
||||||
|
"roc.latency-tuner.profile" = "default";
|
||||||
|
"fec.code" = "default";
|
||||||
|
"sess.latency.msec" = 100;
|
||||||
|
"local.source.port" = sourcePort;
|
||||||
|
"local.repair.port" = repairPort;
|
||||||
|
"local.control.port" = controlPort;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
"pipewire/pipewire.conf.d/52-audio-share-sink.conf".text = builtins.toJSON {
|
||||||
|
"context.modules" = [
|
||||||
|
{
|
||||||
|
name = "libpipewire-module-roc-sink";
|
||||||
|
args = {
|
||||||
|
"fec.code" = "default";
|
||||||
|
"remote.ip" = cfg.partner.ip;
|
||||||
|
"remote.source.port" = sourcePort;
|
||||||
|
"remote.repair.port" = repairPort;
|
||||||
|
"remote.control.port" = controlPort;
|
||||||
|
"sink.props" = {
|
||||||
|
"node.name" = cfg.partner.name;
|
||||||
|
"node.description" = cfg.partner.name;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
name = "libpipewire-module-combine-stream";
|
||||||
|
args = {
|
||||||
|
"combine.mode" = "sink";
|
||||||
|
"node.name" = sinkName;
|
||||||
|
"node.description" = "Shared Audio Output";
|
||||||
|
"combine.latency-compensate" = true;
|
||||||
|
"combine.props" = {
|
||||||
|
audio.position = [
|
||||||
|
"FL"
|
||||||
|
"FR"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
"stream.rules" =
|
||||||
|
let
|
||||||
|
actions = {
|
||||||
|
create-stream = {
|
||||||
|
"combine.audio.position" = [
|
||||||
|
"FL"
|
||||||
|
"FR"
|
||||||
|
];
|
||||||
|
"audio.position" = [
|
||||||
|
"FL"
|
||||||
|
"FR"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in
|
||||||
|
[
|
||||||
|
{
|
||||||
|
matches = [
|
||||||
|
{
|
||||||
|
"media.class" = "Audio/Sink";
|
||||||
|
"node.name" = cfg.partner.combine;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
inherit actions;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
matches = [
|
||||||
|
{
|
||||||
|
"media.class" = "Audio/Sink";
|
||||||
|
"node.name" = cfg.partner.name;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
inherit actions;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
set -eu
|
||||||
|
|
||||||
|
get_id() {
|
||||||
|
pw-dump | jq -r --arg name "$1" '
|
||||||
|
.[]
|
||||||
|
| select(.type == "PipeWire:Interface:Node")
|
||||||
|
| select(.info.props["node.name"] == $name)
|
||||||
|
| .id
|
||||||
|
'
|
||||||
|
}
|
||||||
|
|
||||||
|
ID_A=$(get_id "$SINK_A")
|
||||||
|
ID_B=$(get_id "$SINK_B")
|
||||||
|
|
||||||
|
CURRENT_ID=$(wpctl inspect @DEFAULT_AUDIO_SINK@ |
|
||||||
|
awk '$1 == "id" { gsub(",", "", $2); print $2 }')
|
||||||
|
|
||||||
|
if [ "$CURRENT_ID" = "$ID_A" ]; then
|
||||||
|
wpctl set-default "$ID_B"
|
||||||
|
else
|
||||||
|
wpctl set-default "$ID_A"
|
||||||
|
fi
|
||||||
@@ -66,7 +66,7 @@ in
|
|||||||
sdr_min_luminance = 0.25;
|
sdr_min_luminance = 0.25;
|
||||||
sdr_max_luminance = 250;
|
sdr_max_luminance = 250;
|
||||||
icc = toString ./fv43u.icc;
|
icc = toString ./fv43u.icc;
|
||||||
cm = "dcip3";
|
# cm = "dcip3";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -18,18 +18,31 @@ in
|
|||||||
fonts.fontconfig.subpixel.rgba = "bgr";
|
fonts.fontconfig.subpixel.rgba = "bgr";
|
||||||
|
|
||||||
home-manager.users.${username}.wayland.windowManager.hyprland.settings = {
|
home-manager.users.${username}.wayland.windowManager.hyprland.settings = {
|
||||||
|
config = {
|
||||||
general.layout = "master";
|
general.layout = "master";
|
||||||
master = {
|
master = {
|
||||||
orientation = "right";
|
orientation = "right";
|
||||||
mfact = 0.65;
|
mfact = 0.65;
|
||||||
always_keep_position = true;
|
always_keep_position = true;
|
||||||
};
|
};
|
||||||
monitor = [
|
|
||||||
"HDMI-A-1,2560x1440@75,0x0,1"
|
|
||||||
"DP-1,1920x1080@144,auto-center-right,1,transform,3"
|
|
||||||
];
|
|
||||||
xwayland.force_zero_scaling = true;
|
xwayland.force_zero_scaling = true;
|
||||||
misc.vrr = 0; # VA suffers from VRR flicker
|
misc.vrr = 0; # VA suffers from VRR flicker
|
||||||
};
|
};
|
||||||
|
monitor = [
|
||||||
|
{
|
||||||
|
output = "HDMI-A-1";
|
||||||
|
mode = "2560x1440@75";
|
||||||
|
position = "0x0";
|
||||||
|
scale = 1;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
output = "DP-1";
|
||||||
|
mode = "1920x1080@144";
|
||||||
|
position = "auto-center-right";
|
||||||
|
scale = 1;
|
||||||
|
transform = 3;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ in
|
|||||||
"pulseaudio" = {
|
"pulseaudio" = {
|
||||||
format = "{icon} {volume}%";
|
format = "{icon} {volume}%";
|
||||||
format-icons = {
|
format-icons = {
|
||||||
"alsa_output.usb-Turtle_Beach_Turtle_Beach_Stealth_700_G2_MAX-01.iec958-stereo" = "";
|
"astro-a50-eq-harman-in" = "";
|
||||||
"alsa_output.pci-0000_0a_00.4.analog-stereo" = "";
|
"alsa_output.pci-0000_0a_00.4.analog-stereo" = "";
|
||||||
"alsa_output.pci-0000_08_00.1.hdmi-stereo-extra4" = "";
|
"alsa_output.pci-0000_08_00.1.hdmi-stereo-extra4" = "";
|
||||||
"alsa_output.usb-Blue_Microphones_Yeti_Stereo_Microphone_797_2018_11_12_79383-00.analog-stereo" =
|
"alsa_output.usb-Blue_Microphones_Yeti_Stereo_Microphone_797_2018_11_12_79383-00.analog-stereo" =
|
||||||
|
|||||||
Reference in New Issue
Block a user