Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
0703ad8
Change UI design
RiceaRaul Jul 18, 2025
7f60f91
Change UI design
RiceaRaul Jul 18, 2025
8b783bd
Change UI design
RiceaRaul Jul 18, 2025
4db49bb
Add react query to init the app
RiceaRaul Jul 18, 2025
d76d8a8
Integrate create/delete/list custom sinks into new interface
SFlrn22 Jul 19, 2025
448b1b2
remove return parameter from deleteVirtualSink
SFlrn22 Jul 19, 2025
6b78677
remove unused
SFlrn22 Jul 19, 2025
3deba29
refactor: replace useMutation with useQuery for fetching custom sinks
RiceaRaul Jul 19, 2025
37176c4
Merge remote-tracking branch 'origin/feat/ui-vite' into feat/ui-vite
RiceaRaul Jul 19, 2025
8c8942e
Create interface Query for useQuery methods
RiceaRaul Jul 19, 2025
16c8200
refactor: update query and mutation functions for virtual sinks
RiceaRaul Jul 19, 2025
3a72833
[WIP] Start client-side for dnd
RiceaRaul Jul 19, 2025
5ea1954
Wip move app to sink from dashboard
SFlrn22 Aug 3, 2025
82ee654
refactor: group application streams by device key for bulk operations
RiceaRaul Aug 4, 2025
b93f394
Changes by flowie
RiceaRaul Aug 4, 2025
9b052de
feat: add regex utility for volume parsing and update audio interfaces
RiceaRaul Aug 14, 2025
62b0b75
Fix claudiu fuck application
RiceaRaul Sep 27, 2025
07751c8
Cleanup Complete!
RiceaRaul Nov 2, 2025
9353db7
Add set sink volume
RiceaRaul Nov 2, 2025
9e475ff
Rename misspell queryKEy
RiceaRaul Nov 2, 2025
e764713
refactor: phase 0 cleanup — remove dead UI and fix listener leak
RiceaRaul May 26, 2026
a583882
feat(backend): headset descriptor + device controller (phase 1a)
RiceaRaul May 26, 2026
3693041
feat(frontend): device picker + ChatMix wiring (phase 1b)
RiceaRaul May 26, 2026
e002dd7
feat(backend): per-stream volume + mute (phase 2a)
RiceaRaul May 26, 2026
e2befe7
feat(frontend): wire per-stream volume + mute (phase 2b)
RiceaRaul May 26, 2026
0142ed7
feat(backend): default-sink + port unlink + node ports (phase 3a)
RiceaRaul May 26, 2026
8155c00
feat(frontend): real Sink Manager + Port Link panel (phase 3b)
RiceaRaul May 26, 2026
18d1585
feat(frontend): reusable PageHeader + EmptyState + LoadingSkeleton pr…
RiceaRaul May 26, 2026
e1d8eb1
feat: friendlier stream names + user rename override
RiceaRaul May 26, 2026
225f316
feat(frontend): apply PageHeader + EmptyState + LoadingSkeleton (phas…
RiceaRaul May 26, 2026
8641209
style(frontend): drop redundant bg-gray-50 on HID device textarea (ov…
RiceaRaul May 26, 2026
1884c53
refactor: drop UserNav (no auth, no user account in v0.1)
RiceaRaul May 26, 2026
fe3fc91
chore(release): real README + PenguinWave window title (phase 5 prep)
RiceaRaul May 26, 2026
0d75124
style(frontend): modernize typography + token discipline
RiceaRaul May 26, 2026
0d04e42
refactor(frontend): full layout rethink — hero panel, flat lists, sid…
RiceaRaul May 26, 2026
29598b8
style(frontend): kill em-dashes + drop dead import
RiceaRaul May 26, 2026
2725394
refactor(routing): rethink DndBoard composition
RiceaRaul May 26, 2026
1340796
feat: drag-to-unassign streams back to default sink
RiceaRaul May 26, 2026
5b4a182
feat: friendly sink labels (game_sink → Game, chat_sink → Chat)
RiceaRaul May 26, 2026
875a15a
feat: remember pre-custom sink, restore on unassign
RiceaRaul May 26, 2026
abe2914
fix(routing): stop double-showing apps after partial sink moves
RiceaRaul May 26, 2026
82d06c1
feat(maintenance): add maintenance page for udev rules and system deps
RiceaRaul Jun 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 62 additions & 4 deletions PenguinWave/README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,65 @@
# Tauri + React + Typescript
# PenguinWave

This template should help get you started developing with Tauri, React and Typescript in Vite.
PipeWire virtual-sink manager for Linux gamers. Route per-app audio between virtual sinks and drive your headset's ChatMix wheel from one place.

## Recommended IDE Setup
> v0.1 — desktop-only, Linux-only. Tested on Arch (CachyOS).

- [VS Code](https://code.visualstudio.com/) + [Tauri](https://marketplace.visualstudio.com/items?itemName=tauri-apps.tauri-vscode) + [rust-analyzer](https://marketplace.visualstudio.com/items?itemName=rust-lang.rust-analyzer)
## What it does

- **Virtual sinks**: creates `game_sink` + `chat_sink` on first launch; lets you create / delete more.
- **Per-app routing**: drag-and-drop applications between sinks, or pick from a dropdown.
- **Per-stream volume + mute**: real `pactl set-sink-input-volume` / `set-sink-input-mute`, debounced sliders.
- **ChatMix wheel integration**: turn your headset wheel, watch the slider move and the game/chat sink volumes flip live.
- **Port linking**: a power-user panel to wire any source output port to any target input port (`pw-link`).
- **Friendlier stream names**: falls back from `application.name` to `application.process.binary` to `/proc/<pid>/cmdline` to a `media.role`-based hybrid label. Rename anything inline (persisted to `localStorage`).

## Supported headsets (v0.1)

- SteelSeries Arctis Nova 7

Adding more is a matter of implementing `DeviceTrait` in `src-tauri/src/headsets/` and registering it in `AppStateManager::initialize_supported_devices`.

## Requirements

- **PipeWire** userland: `pactl`, `pw-cli`, `pw-link` on PATH (Debian/Ubuntu: `pipewire pipewire-pulse pipewire-cli`; Arch: `pipewire pipewire-pulse wireplumber`).
- **Linux** only — uses `/proc` and HID via `hidapi`.
- HID device permissions for headset access (udev rules typically grant via `plugdev` / `input` group).

## Install (from source)

```bash
git clone <repo> penguinwave
cd penguinwave
npm install
npm run tauri:build
# .deb / AppImage ends up in src-tauri/target/release/bundle/
```

## Run in dev

```bash
npm run tauri:debug # full app, RUST_BACKTRACE=full RUST_LOG=debug
npm run dev # frontend only on http://localhost:1420 (no Tauri commands)
```

## Architecture

```
React (Vite) ──invoke──▶ Tauri 2 commands ──shell out──▶ pactl / pw-cli / pw-link
▲ │ │
│ ▼ ▼
listen() ◀──emit───── chatmix poll thread (100ms) ◀──HID── hidapi
```

- Frontend: React 18, TanStack Query 5, wouter, Radix + shadcn/ui (style "new-york"), Tailwind 3.
- Backend: Rust edition 2021, Tauri 2, `hidapi`, `anyhow`/`thiserror`.

## Project layout

- `src/` — React frontend (pages, components, hooks, queries, types).
- `src-tauri/` — Rust crate (`controllers/`, `system/pipewire.rs`, `event/chatmix_listener.rs`, `headsets/`, `utils/`).
- `shared/` — vestigial Drizzle schema (not wired up).

## License

TBD.
2 changes: 1 addition & 1 deletion PenguinWave/RunConfigurations/RunDevServer.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<scripts>
<script value="dev" />
</scripts>
<node-interpreter value="project" />
<node-interpreter value="$USER_HOME$/.nvm/versions/node/v24.16.0/bin/node" />
<envs />
<method v="2" />
</configuration>
Expand Down
4 changes: 3 additions & 1 deletion PenguinWave/RunConfigurations/RunTauriApp.run.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
<option name="buildProfileId" value="dev" />
<option name="command" value="run --no-default-features" />
<option name="workingDirectory" value="file://$PROJECT_DIR$/src-tauri" />
<envs />
<envs>
<env name="RUST_BACKTRACE" value="full" />
</envs>
<option name="emulateTerminal" value="true" />
<option name="channel" value="DEFAULT" />
<option name="requiredFeatures" value="true" />
Expand Down
20 changes: 20 additions & 0 deletions PenguinWave/components.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": false,
"tsx": true,
"tailwind": {
"config": "tailwind.config.ts",
"css": "src/index.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
}
}
6 changes: 3 additions & 3 deletions PenguinWave/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Tauri + React + Typescript</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1" />
<title>PenguinWave</title>
<meta name="description" content="PipeWire virtual-sink manager. Route per-app audio between sinks and drive your headset's ChatMix wheel." />
</head>

<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
Expand Down
Loading
Loading