diff options
| author | vin <vin@vineetk.net> | 2025-09-21 14:24:00 -0400 |
|---|---|---|
| committer | vin <vin@vineetk.net> | 2025-09-21 14:24:00 -0400 |
| commit | 157caffbeba0945103f60b625f8f78a1d7777fc1 (patch) | |
| tree | 47c4ecc63e31e0105ef4108214d0f77213e1a780 /hosts | |
| parent | 6384bec28fdfee01797cfb3e2d13d27b59e3da3b (diff) | |
begrudgingly go back to pipewire
fighting against it is hard, especially on nixos and when I want steam
Diffstat (limited to 'hosts')
| -rw-r--r-- | hosts/demiurge/default.nix | 135 |
1 files changed, 23 insertions, 112 deletions
diff --git a/hosts/demiurge/default.nix b/hosts/demiurge/default.nix index 9f35926..10d2cbe 100644 --- a/hosts/demiurge/default.nix +++ b/hosts/demiurge/default.nix | |||
| @@ -247,8 +247,10 @@ | |||
| 247 | } | 247 | } |
| 248 | ]; | 248 | ]; |
| 249 | }; | 249 | }; |
| 250 | |||
| 251 | sudo.enable = false; | 250 | sudo.enable = false; |
| 251 | |||
| 252 | # needed to give realtime privileges to pipewire | ||
| 253 | rtkit.enable = true; | ||
| 252 | }; | 254 | }; |
| 253 | 255 | ||
| 254 | services = { | 256 | services = { |
| @@ -478,122 +480,31 @@ | |||
| 478 | alsa.enable = true; | 480 | alsa.enable = true; |
| 479 | audio.enable = true; | 481 | audio.enable = true; |
| 480 | pulse.enable = true; | 482 | pulse.enable = true; |
| 481 | |||
| 482 | extraConfig.pipewire = { | ||
| 483 | "99-filter-he5xx.conf" = { | ||
| 484 | "context.modules" = [ | ||
| 485 | { | ||
| 486 | name = "libpipewire-module-filter-chain"; | ||
| 487 | args = { | ||
| 488 | node.name = "peq-he5xx-sink"; | ||
| 489 | node.description = "PEQ HE5XX (auto)"; | ||
| 490 | # playback.props is the virtual sink/device properties | ||
| 491 | playback.props = { | ||
| 492 | media.class = "Audio/Sink"; | ||
| 493 | "filter.smart" = true; | ||
| 494 | "filter.smart.name" = "peq-he5xx"; | ||
| 495 | # tell WirePlumber what target properties this filter is intended for | ||
| 496 | # (we leave this unset here; smart target matching will be done by wireplumber) | ||
| 497 | }; | ||
| 498 | # filter graph: single builtin param_eq node that loads the param file | ||
| 499 | filter.graph = [ | ||
| 500 | { | ||
| 501 | type = "builtin"; | ||
| 502 | name = "param_eq"; | ||
| 503 | label = "param_eq_he5xx"; | ||
| 504 | config.filename = "/etc/pipewire/parametric/he5xx.txt"; | ||
| 505 | } | ||
| 506 | ]; | ||
| 507 | }; | ||
| 508 | } | ||
| 509 | ]; | ||
| 510 | }; | ||
| 511 | |||
| 512 | "99-filter-airpods.conf" = { | ||
| 513 | "context.modules" = [ | ||
| 514 | { | ||
| 515 | name = "libpipewire-module-filter-chain"; | ||
| 516 | args = { | ||
| 517 | node.name = "peq-airpods-pro-2-sink"; | ||
| 518 | node.description = "PEQ AirPods Pro 2 (auto)"; | ||
| 519 | playback.props = { | ||
| 520 | media.class = "Audio/Sink"; | ||
| 521 | "filter.smart" = true; | ||
| 522 | "filter.smart.name" = "peq-airpods-pro-2"; | ||
| 523 | }; | ||
| 524 | filter.graph = [ | ||
| 525 | { | ||
| 526 | type = "builtin"; | ||
| 527 | name = "param_eq"; | ||
| 528 | label = "param_eq_airpods"; | ||
| 529 | config.filename = "/etc/pipewire/parametric/airpods-pro-2.txt"; | ||
| 530 | } | ||
| 531 | ]; | ||
| 532 | }; | ||
| 533 | } | ||
| 534 | ]; | ||
| 535 | }; | ||
| 536 | }; | ||
| 537 | |||
| 538 | wireplumber = { | 483 | wireplumber = { |
| 539 | enable = true; | 484 | enable = true; |
| 540 | extraConfig."50-smartfilters-airpods.conf".text = '' | 485 | extraConfig = { |
| 541 | { | 486 | "51-set-default-eq.conf" = { |
| 542 | "monitor.bluez.rules" : [ | 487 | text = '' |
| 543 | # When a BlueZ device is detected we set an identifying property that the smart filter will match. | 488 | monitor.rules = [ |
| 544 | # (This fragment adds nothing by default; we're using a policy to match target.node later.) | 489 | { |
| 545 | ], | 490 | matches = [ |
| 546 | 491 | { | |
| 547 | "policy.rules" : [ | 492 | # This rule matches the node with the name of your sink (node 35) |
| 548 | # The core smart filter matching is done by matching the target.node properties | 493 | "node.name" = "effect_input.eq6" |
| 549 | # WirePlumber's smart filters will look for filter.smart.target (set below). | 494 | } |
| 550 | ], | 495 | ] |
| 551 | 496 | actions = { | |
| 552 | "policy" : { | 497 | update-props = { |
| 553 | "smart_filters" : { | 498 | # This sets a very high priority, making it the default. |
| 554 | "rules" : [ | 499 | # Standard hardware is usually around 1000. |
| 555 | { | 500 | "priority.session" = 2001 |
| 556 | "matches" : [ | ||
| 557 | { "device.props" : { "bluez5.device.name" : "AirPods Pro 2" } } | ||
| 558 | ], | ||
| 559 | "actions" : { | ||
| 560 | # If target device matches, set the 'target.node' metadata for smart filters to use | ||
| 561 | "update-metadata" : { | ||
| 562 | "target.node" : { "name" : "bluez_output.*AirPods.*" } | ||
| 563 | } | ||
| 564 | } | 501 | } |
| 565 | } | ||
| 566 | ] | ||
| 567 | } | ||
| 568 | }, | ||
| 569 | |||
| 570 | "endpoint.rules" : [ | ||
| 571 | { | ||
| 572 | "matches" : [ | ||
| 573 | { "node.name" : "peq-airpods-pro-2-sink" } | ||
| 574 | ], | ||
| 575 | "actions" : { | ||
| 576 | "update-props" : { | ||
| 577 | # Mark this WF sink as intended for a specific target device. | ||
| 578 | # WirePlumber will use filter.smart.target to identify which device to chain to. | ||
| 579 | "filter.smart.target" : { "bluez5.device.name" : "AirPods Pro 2" } | ||
| 580 | } | ||
| 581 | } | ||
| 582 | }, | ||
| 583 | { | ||
| 584 | "matches" : [ | ||
| 585 | { "node.name" : "peq-he5xx-sink" } | ||
| 586 | ], | ||
| 587 | "actions" : { | ||
| 588 | "update-props" : { | ||
| 589 | # He5xx is a generic filter (no specific bluez target) — it could be matched by other rules. | ||
| 590 | "filter.smart.target" : {} | ||
| 591 | } | 502 | } |
| 592 | } | 503 | } |
| 593 | } | 504 | ] |
| 594 | ] | 505 | ''; |
| 595 | } | 506 | }; |
| 596 | ''; | 507 | }; |
| 597 | }; | 508 | }; |
| 598 | }; | 509 | }; |
| 599 | 510 | ||
