summaryrefslogtreecommitdiff
path: root/TODO
blob: 123438859d364a2fe920d1125111df0e49a60130 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
tmix — todo list
================

## UAT checklist
Run through this before any release / major refactor.

### Startup
- [ ] App launches without crash when PA is running
- [ ] App launches without crash when PA is NOT running (graceful fail)
- [ ] Tray icon appears when DockInTray=true
- [ ] Window hidden on launch when DockInTray=true
- [ ] Window visible on launch when DockInTray=false

### Tabs / device population
- [ ] Output tab shows all PA sinks (hardware outputs)
- [ ] Input tab shows all PA sources (mics etc.) but NOT monitor sources
- [ ] Playback tab shows per-app sink inputs; tmix-peak streams NOT shown
- [ ] Recording tab shows per-app source outputs; tmix-peak streams NOT shown
- [ ] Devices added/removed live without restart (plug/unplug USB audio, start/stop app)
- [ ] Correct icon shown per device (headphone, microphone, digital, fallback)
- [ ] Correct app icon shown for Playback streams (Amarok, Firefox, etc.)
- [ ] Vertical label shows device/stream name

### Volume
- [ ] Dragging volume slider changes PA volume in real time
- [ ] Volume % label updates live while dragging
- [ ] Scrolling on tray icon changes default output volume
- [ ] Volume change from another app (pavucontrol) reflects in tmix slider + label
- [ ] Volume clamped 0–100%, no overflow

### Mute
- [ ] Green LED = unmuted, off = muted
- [ ] Clicking LED toggles mute state in PA
- [ ] Mute change from another app reflects in LED
- [ ] Right-click "Mute" mutes; item shows "Muted" with checkmark when muted; "Unmute" when muted

### Balance knob (Output + Playback only)
- [ ] Knob renders cleanly (antialiased, no flicker)
- [ ] Dragging up increases right balance, dragging down increases left
- [ ] Scroll wheel adjusts ±5
- [ ] Double-click resets to centre
- [ ] PA channel volumes update correctly (left attenuated when right-heavy)
- [ ] Balance change from pavucontrol reflects in knob
- [ ] Input tab has NO balance knob

### Level meter
- [ ] Output: meter responds to audio playback through that sink
- [ ] Input: meter responds to microphone input
- [ ] Playback: meter shows per-stream level (only that app's audio, not the whole sink)
- [ ] Recording: meter shows source level (forwarded from parent source signal)
- [ ] Meter decays smoothly; attack is fast, decay is slower
- [ ] Meter shows 0 when muted or silent

### Default device
- [ ] Radio button filled on the current PA default output
- [ ] Radio button filled on the current PA default input
- [ ] Clicking empty radio button sets that device as PA default
- [ ] Default change from pavucontrol updates radio buttons in tmix
- [ ] Only one radio button filled at a time per tab
- [ ] Tray icon reflects default output volume/mute state

### Recording indicator
- [ ] Red LED on Input widget is OFF when no app is recording from that source
- [ ] Red LED turns ON when an app starts recording from that source
- [ ] Red LED turns OFF when recording app stops
- [ ] Second tray icon (microphone) appears when any input is active
- [ ] Second tray icon disappears when all recording stops

### Right-click context menu
- [ ] Right-click on any device widget shows context menu
- [ ] Menu title shows device name
- [ ] "Mute"/"Muted" item works (see Mute section)
- [ ] Output: "Set as Default Output" present and functional
- [ ] Input: "Set as Default Input" present and functional
- [ ] Playback: "Move to Sink" section lists all available sinks
- [ ] Current sink shown with checkmark in "Move to Sink" list
- [ ] Selecting a different sink moves the stream
- [ ] Output/Input: no "Move to Sink" section
- [ ] Playback/Recording: no "Set as Default" item

### System tray
- [ ] Volume icon shows muted/low/medium/high based on default output
- [ ] Icon updates when volume changes (slider, scroll wheel, external)
- [ ] Icon updates when mute state changes
- [ ] Scroll wheel on tray raises/lowers default output volume
- [ ] Left-click tray shows/hides main window
- [ ] Right-click tray shows context menu with Quit (only one Quit entry)

### Window behaviour
- [ ] Closing window hides to tray (DockInTray=true), does not quit
- [ ] Closing window quits (DockInTray=false)
- [ ] Session logout closes app cleanly (sessionSaving check)
- [ ] File → Quit exits cleanly, no crash or double-free

### Stress / edge cases
- [ ] Rapidly toggle mute — no crash, no stuck state
- [ ] Rapidly drag slider — no crash, PA not flooded beyond responsiveness
- [ ] Kill and restart PulseAudio while tmix is open — tmix recovers or fails gracefully
- [ ] Open tmix with 0 devices on each tab — no crash, empty tabs look OK
- [ ] Open tmix with 10+ playback streams — layout scrolls, no overlap

## Bugs / Polish
- [x] Taskbar / dock icon missing
- [x] Recording tray icon red dot not appearing
- [x] Icons: app-specific icons for Firefox etc.
- [x] Input devices always show microphone icon regardless of PA device name hint
- [x] Right-click "Move to Sink": show checkmark on the sink the stream is currently on
- [x] Right-click mute item: fixed label "Mute" with checkmark when muted
- [x] Scroll area for 10+ devices — TQScrollView wrapping tab pages and flat strip;
      scroll bars appear only when content exceeds window width
- [x] Window does not resize on card profile change (removed adjustSize())
- [x] Window position persists across restarts
- [x] Single-instance enforcement — second launch raises/shows the existing window (KUniqueApplication)
- [x] Settings dialog is non-blocking (modeless, false modal param in KDialogBase ctor)
- [ ] Devices tab — sex it up vs pavucontrol-qt:
      - Port availability indicators (plugged/unplugged) with port-type icons
        (headphones, mic, HDMI, speaker, S/PDIF) from pa_card_port_info.type
      - availability_group handling: when a combo jack is detected (multiple ports
        share an availability_group), show a "What did you plug in?" prompt so the
        user can disambiguate headphones vs headset vs mic
      - Hide unavailable profiles by default (toggle to show all)

## Features

### Implemented
- [x] Volume % label (live, updates on drag)
- [x] Pan / balance slider per stereo device (reads + writes PA per-channel cvolume)
- [x] Level meter — Output/Input via sink/source monitor; Playback via pa_stream_set_monitor_stream (per-stream)
- [x] Slider tick marks every 5%
- [x] Separator between devices
- [x] Playback slider fix (was broken due to hardcoded 2-channel cvolume)
- [x] Mute button: 3D toggle style
- [x] App icons with multimedia fallback; amarok/TDE apps resolve via binary name
- [x] tmix-peak streams hidden from Recording tab and pavucontrol (media.role=abstract)
- [x] Menu bar — File: Quit, Settings: Configure TMix, Help: About TMix
- [x] Per-device right-click context menu — mute (checkmark), set default, move to sink (checkmark on current)
- [x] System tray (KSystemTray) — scroll wheel adjusts default sink volume, left-click popup/window toggle
- [x] Tray icon — SmallIcon("kmix")/("audio-volume-medium") fallback; muted/low/medium/high states
- [x] Tray popup (TmixPopup) — left-click, shows default output DeviceWidget + "Mixer" button,
      auto-dismiss on outside click, positions above/below tray, stays on top
- [x] Recording tray icon — second KSystemTray icon when any input is active;
      tooltip lists names of active recording streams
- [x] "Show all in one view" (no-tabs mode) — TQWidgetStack, rebuilds on toggle,
      live device add/remove works in both modes
- [x] Show/hide individual tabs (Output, Input, Playback, Recording) via preferences
- [x] Preferences dialog — modeless (non-blocking), OK+Apply+Cancel,
      General: dock in tray, popup on click, rec tray icon, confirm quit, scroll step
      View: no-tabs toggle, show/hide per tab
- [x] Window auto-sizes to content (adjustSize on device add/remove), minimum 300×200
- [x] Bottom row fixed 30px height — all device widgets align regardless of content

### To do
- [x] Devices tab — PA card profile switcher (dropdown per card, set active profile)
- [x] Port switching in Devices tab — Output port / Input port dropdowns per card
      (pa_context_set_sink_port_by_index / set_source_port_by_index); only shown
      when a sink/source has 2+ ports. Active port updates in-place on PA events.
- [ ] Profiles / sources management tab
      List all PA sources and sinks with their active profile (e.g. "analog-stereo",
      "hdmi-stereo-extra1"). Allow switching profiles via dropdown.
      Show default sink/source with a star; click to set new default
      (pa_context_set_default_sink / pa_context_set_default_source).
      Subscribe to PA_SUBSCRIPTION_MASK_SERVER + CARD for live updates.
- [x] Tray right-click: Configure, About, Quit (standard TDE style — no functional items)
- [x] Remember window geometry across restarts

## Big Refactor — Backend Abstraction
Goal: replace KMix entirely across all Trinity platforms (Linux PA/PW/ALSA, FreeBSD OSS,
legacy systems). Each backend is self-contained end-to-end: its own model, its own widgets.
The main window is a dumb shell.

Architecture:
  AbstractBackend (minimal interface)
    - name() / open() / close()
    - createMixerWidget(parent)  → TQWidget*
    - createDevicesWidget(parent)→ TQWidget* (null if not supported)

  PulseAudioBackend : AbstractBackend  — current code, reorganised
  OSSBackend        : AbstractBackend  — flat sliders, no streams
  AlsaBackend       : AbstractBackend  — HDA controls, switches
  PipeWireBackend   : AbstractBackend  — routing graph if ever needed

  MixerWindow shrinks to: tray, menu, prefs, geometry, "host what backend gives me."
  Shared UI widgets (DeviceWidget, LevelMeter, BalanceKnob) become a toolkit
  backends may use or ignore — not a framework they're forced into.

  Backend selected at startup via config key "Backend" (default: pulseaudio).
  Build system conditionally compiles backends per platform.

Why: the OSS→ALSA→PA retrofit history was painful. No backend should ever know
about another; no generic UI code should check backend capabilities via flags.
- [ ] DCOP interface (get/set volume, mute, list devices)
- [ ] Horizontal layout mode — device strips laid out left-to-right instead of
      top-to-bottom; label above slider, level meter beside it. Toggle in View menu.
- [ ] Current mixer selector — dropdown or sub-menu to switch between PulseAudio
      and raw ALSA hardware cards (like KMix "Current Mixer"). Each card gets its
      own tab set; PA is the default. Enumerate via pa_context_get_card_info_list
      for PA cards; snd_ctl_open for ALSA HDA cards.
- [ ] Popup config options (Settings → General):
      Popup content: default output only (default) | all outputs | active playback streams
      Show level meter in popup: yes/no (saves vertical space)

## Settings / Polish (do later)
- [ ] Settings dialog: switch from KDialogBase Tabbed to IconList style (like KMix) —
      big sidebar icons (General, View, etc.) with page content on the right.
- [ ] Settings dialog: Defaults button, Help button
- [ ] Settings dialog: grey out Apply until a change is actually made
- [ ] Show/hide toggles for tickmarks, labels, level meters (View tab)

## Distribution / Integration
- [ ] .desktop file + icon
- [ ] CMake install rules (bin, desktop, icon)
- [ ] PipeWire-native backend (currently works via PW's PA compatibility layer)
- [ ] Package as trinity-mixer