{"id":34121212,"url":"https://github.com/xaionaro-go/pw-pin","last_synced_at":"2026-03-12T05:36:01.862Z","repository":{"id":310130569,"uuid":"1038819872","full_name":"xaionaro-go/pw-pin","owner":"xaionaro-go","description":"Simple pinning of pipewire connections","archived":false,"fork":false,"pushed_at":"2025-10-12T16:26:10.000Z","size":61,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-17T07:36:59.540Z","etag":null,"topics":["audio","go","golang","linux","pin","pipewire","pw","routing","simple","sound","wireplumber","wiring"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"cc0-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xaionaro-go.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-15T22:00:33.000Z","updated_at":"2025-10-12T16:26:14.000Z","dependencies_parsed_at":"2025-08-21T17:03:02.425Z","dependency_job_id":null,"html_url":"https://github.com/xaionaro-go/pw-pin","commit_stats":null,"previous_names":["xaionaro-go/simpleplumber","xaionaro-go/pw-pin"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/xaionaro-go/pw-pin","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xaionaro-go%2Fpw-pin","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xaionaro-go%2Fpw-pin/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xaionaro-go%2Fpw-pin/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xaionaro-go%2Fpw-pin/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xaionaro-go","download_url":"https://codeload.github.com/xaionaro-go/pw-pin/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xaionaro-go%2Fpw-pin/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30416316,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-12T04:41:02.746Z","status":"ssl_error","status_checked_at":"2026-03-12T04:40:12.571Z","response_time":114,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audio","go","golang","linux","pin","pipewire","pw","routing","simple","sound","wireplumber","wiring"],"created_at":"2025-12-14T21:46:57.243Z","updated_at":"2026-03-12T05:36:01.857Z","avatar_url":"https://github.com/xaionaro-go.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `pw-pin`\n\n`wireplumber` broke a lot of compatibility from 0.4 to 0.5, while writing scripts for each of them is a big time investment (personally for me). And this is severely exacerbated by absence of necessary docs. At the same time I have few streaming-studio related workstations where I just need some wiring done no matter what with minimal effort. As a result I decided to write this small ugly service.\n\nThis service is supposed to be running in parallel to `wireplumber` (or alternative). However, it is also useable as a minimalistic replacement.\n\n## Quick start\n\nInstall\n```sh\ngo install github.com/xaionaro-go/pw-pin/cmd/pw-pind@main\n```\n\nConfigure:\n```sh\nmkdir -p ~/.config/pw-pin\ncat \u003e ~/.config/pw-pin/config.conf \u003c\u003cEOF\n```\n```yaml\nroutes:\n    - from: # to link mpv (matched loosely) with RODECaster Duo (left channel)\n        node:\n            - property: media.name\n              values: [' - mpv']\n              op: CONTAINS\n        port:\n            - property: port.name\n              values: [output_FL]\n      to:\n        node:\n            - property: node.name\n              values: [alsa_output.usb-R__DE_RODECaster_Duo_IR0037235-00.pro-output-0]\n        port:\n            - property: port.name\n              values: [playback_AUX0]\n      should_be_linked: true\n    - from: # to link mpv (matched loosely) with RODECaster Duo (right channel)\n        node:\n            - property: media.name\n              values: [' - mpv']\n              op: CONTAINS\n        port:\n            - property: port.name\n              values: [output_FR]\n      to:\n        node:\n            - property: node.name\n              values: [alsa_output.usb-R__DE_RODECaster_Duo_IR0037235-00.pro-output-0]\n        port:\n            - property: port.name\n              values: [playback_AUX1]\n      should_be_linked: true\n    - from: # to do not unlink from volume meters (e.g. pavucontrol)\n        node:\n            - property: media.name\n              values: [' - mpv']\n              op: CONTAINS\n      to:\n        node:\n            - property: media.name\n              values: [Peak detect]\n      should_be_linked: null # \u003c- means: keep as is; but since we already matched this rule, we won't get to the next one\n    - from: # to unlink it from everything else\n        node:\n            - property: media.name\n              values: [' - mpv']\n              op: CONTAINS\n      should_be_linked: false\n```\n```sh\nEOF\n```\n(for the information which properties exist, see `pw-dump`)\n\nRun:\n```sh\n\"$(go env GOPATH)\"/bin/pw-pind\n```\n\nAn example of output:\n```sh\nstreaming@void:~/go/src/github.com/xaionaro-go/pw-pin$ ~/go/bin/pw-pind\nINFO[0000]main.go:70 started\nINFO[0005]run.go:33 link {\"From\":{\"NodeID\":206,\"PortID\":208},\"To\":{\"NodeID\":114,\"PortID\":145}} created\nINFO[0005]run.go:56 link {\"From\":{\"NodeID\":206,\"PortID\":208},\"To\":{\"NodeID\":74,\"PortID\":137}} destroyed\nINFO[0005]run.go:56 link {\"From\":{\"NodeID\":206,\"PortID\":208},\"To\":{\"NodeID\":319,\"PortID\":203}} destroyed\n```\n\nIf you need more info about `property`-ies mentioned in the config, try running (see `props`):\n```sh\npw-dump --monitor\n```\n\nAs an ugly but simple solution to make `pw-pind` run together with `pipewire`, run (under your normal user account):\n```sh\nmkdir -p ~/.local/bin\ncat \u003e ~/.local/bin/run-pw-pin.sh \u003c\u003cEOF\n#!/bin/bash\nkillall -9 pw-pind\n~/go/bin/pw-pind \"\\$@\" \u0026\nEOF\nchmod +x ~/.local/bin/run-pw-pin.sh\n```\nthen:\n```sh\nsystemctl edit --user pipewire\n```\nand add there:\n```sh\n[Service]\nExecStartPost=~/.local/bin/run-pw-pin.sh\n```\nThis is abuse of `ExecStartPost`, you generally should not do that. But it is very simple, and it works. A better solution would be to write another service file and build a guarantee one is always executed on any `pipewire` restart.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxaionaro-go%2Fpw-pin","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxaionaro-go%2Fpw-pin","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxaionaro-go%2Fpw-pin/lists"}