mini-eq 0.3.2__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mini_eq-0.3.2 → mini_eq-0.4.0}/AGENTS.md +19 -1
- {mini_eq-0.3.2 → mini_eq-0.4.0}/CHANGELOG.md +11 -0
- {mini_eq-0.3.2/src/mini_eq.egg-info → mini_eq-0.4.0}/PKG-INFO +3 -1
- {mini_eq-0.3.2 → mini_eq-0.4.0}/README.md +2 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/data/io.github.bhack.mini-eq.metainfo.xml +11 -2
- {mini_eq-0.3.2 → mini_eq-0.4.0}/docs/release.md +49 -3
- {mini_eq-0.3.2 → mini_eq-0.4.0}/extensions/gnome-shell/mini-eq@bhack.github.io/extension.js +22 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/pyproject.toml +1 -1
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/app.py +71 -11
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/appearance.py +5 -30
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/assets/icons/hicolor/scalable/apps/io.github.bhack.mini-eq.svg +1 -1
- mini_eq-0.4.0/src/mini_eq/background.py +280 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/cli.py +5 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/dbus_control.py +70 -0
- mini_eq-0.4.0/src/mini_eq/settings.py +62 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/window.py +20 -5
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/window_analyzer.py +2 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/window_layout.py +2 -0
- mini_eq-0.4.0/src/mini_eq/window_preferences.py +143 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/wireplumber_backend.py +31 -68
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/wireplumber_stream_router.py +53 -20
- {mini_eq-0.3.2 → mini_eq-0.4.0/src/mini_eq.egg-info}/PKG-INFO +3 -1
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq.egg-info/SOURCES.txt +6 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_gnome_shell_extension.py +4 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_app.py +43 -1
- mini_eq-0.4.0/tests/test_mini_eq_background.py +73 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_dbus_control.py +40 -1
- mini_eq-0.4.0/tests/test_mini_eq_settings.py +35 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_window.py +73 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_window_analyzer.py +4 -1
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_wireplumber_backend.py +139 -47
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_wireplumber_stream_router.py +22 -11
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/check_flatpak_runtime.py +134 -27
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/check_gnome_shell_extension.py +51 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/gnome-shell-extension/fake_mini_eq_control.py +25 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/release_preflight.py +129 -25
- mini_eq-0.4.0/tools/run_flatpak_runtime_smoke_ci.sh +173 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/LICENSE +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/MANIFEST.in +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/SECURITY.md +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/data/io.github.bhack.mini-eq.desktop +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/docker/ubuntu-24.04-wp04.Dockerfile +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/docs/flathub.md +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/docs/performance.md +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/docs/screenshots/README.md +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/docs/screenshots/mini-eq-dark.png +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/docs/screenshots/mini-eq.png +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/docs/social-preview.png +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/extensions/gnome-shell/README.md +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/extensions/gnome-shell/mini-eq@bhack.github.io/metadata.json +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/extensions/gnome-shell/mini-eq@bhack.github.io/mini-eq-symbolic.svg +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/flatpak/patches/wireplumber-0.5.14-tools-disabled-po.patch +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/io.github.bhack.mini-eq.yaml +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/python3-dependencies.yaml +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/setup.cfg +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/__init__.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/__main__.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/analyzer.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/analyzer_widget.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/assets/icons/hicolor/symbolic/apps/io.github.bhack.mini-eq-symbolic.svg +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/band_fader.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/core.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/deps.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/desktop_integration.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/ebur128.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/filter_chain.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/glib_utils.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/gtk_utils.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/instance.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/routing.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/screenshot.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/style.css +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/window_graph.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/window_headroom.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/window_presets.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/window_utility.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq/window_utils.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq.egg-info/dependency_links.txt +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq.egg-info/entry_points.txt +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq.egg-info/requires.txt +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/src/mini_eq.egg-info/top_level.txt +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_analyzer.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_appearance.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_cli.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_core.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_deps.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_desktop_integration.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_ebur128.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_filter_chain.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_instance.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_output_presets.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_routing.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_mini_eq_window_graph.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tests/test_version_metadata.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/benchmark_fader_drag.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/check_flathub_manifest_drift.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/check_wireplumber_gi.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/demo_runtime.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/pack_gnome_shell_extension.sh +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/profile_live_app.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/profile_sysprof.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/release_post_publish.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/render_demo_screenshot.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/render_social_preview.py +0 -0
- {mini_eq-0.3.2 → mini_eq-0.4.0}/tools/run_gnome_extension_dev_shell.sh +0 -0
|
@@ -79,6 +79,13 @@ are unavailable.
|
|
|
79
79
|
only when the user asked for that refactor or the change needs it.
|
|
80
80
|
- Keep WirePlumber 0.4 and 0.5 compatibility in mind. Do not use a newer GI API
|
|
81
81
|
without checking the compatibility layer and tests.
|
|
82
|
+
- Treat the Mini EQ D-Bus control interface as a project-internal app/Shell
|
|
83
|
+
extension contract with version-skew tolerance. Keep `api_version = 1`
|
|
84
|
+
additive only: add state fields, methods, and capabilities when needed, but do
|
|
85
|
+
not remove or rename existing v1 members. Gate optional Shell extension
|
|
86
|
+
behavior on `capabilities`. Bump the API version only for semantic breaks, and
|
|
87
|
+
support the old version for a short, documented release window before removing
|
|
88
|
+
it.
|
|
82
89
|
- Keep the `mini-eq` CLI user-oriented. Maintainer automation belongs in
|
|
83
90
|
`tools/`, `docs/`, or this file.
|
|
84
91
|
- Keep the GNOME Shell extension source in `extensions/gnome-shell/`; do not
|
|
@@ -159,7 +166,10 @@ During release preparation, verify that version-bearing files agree:
|
|
|
159
166
|
URL. The package `__version__` is derived from release metadata and should not
|
|
160
167
|
be hardcoded separately.
|
|
161
168
|
|
|
162
|
-
Before publishing artifacts, run
|
|
169
|
+
Before publishing artifacts, run `tools/release_preflight.py`; its focused leak
|
|
170
|
+
scan covers `HEAD`, tracked worktree changes, and untracked non-ignored text
|
|
171
|
+
files. If reproducing the scan manually, check all three surfaces instead of
|
|
172
|
+
only committed history:
|
|
163
173
|
|
|
164
174
|
```bash
|
|
165
175
|
git rev-list --count HEAD
|
|
@@ -171,6 +181,14 @@ git grep -n -I -E "$leak_pattern" HEAD -- . \
|
|
|
171
181
|
':(exclude)AGENTS.md' \
|
|
172
182
|
':(exclude)docs/release.md' \
|
|
173
183
|
':(exclude)tools/release_preflight.py'
|
|
184
|
+
git grep -n -I -E "$leak_pattern" -- . \
|
|
185
|
+
':(exclude)*.png' \
|
|
186
|
+
':(exclude)AGENTS.md' \
|
|
187
|
+
':(exclude)docs/release.md' \
|
|
188
|
+
':(exclude)tools/release_preflight.py'
|
|
189
|
+
git ls-files --others --exclude-standard -z -- . \
|
|
190
|
+
| grep -z -v -E '(^|/)(AGENTS\.md|docs/release\.md|tools/release_preflight\.py)$|\.png$' \
|
|
191
|
+
| xargs -0 -r grep -n -I -E "$leak_pattern" --
|
|
174
192
|
```
|
|
175
193
|
|
|
176
194
|
Do not push local scratch branches or local safety tags.
|
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0 - 2026-05-05
|
|
4
|
+
|
|
5
|
+
- Add opt-in background mode so closing the window can keep Mini EQ active.
|
|
6
|
+
- Add Start at Login support through the Background portal in Flatpak and XDG
|
|
7
|
+
autostart for native installs.
|
|
8
|
+
- Add D-Bus state fields and a Quit method for Shell extension compatibility.
|
|
9
|
+
- Keep GNOME event sounds, notifications, and other system streams out of
|
|
10
|
+
system-wide EQ routing.
|
|
11
|
+
- Route streams by writing both PipeWire `target.node` and `target.object`
|
|
12
|
+
metadata, avoiding metadata readback as a routing acknowledgement.
|
|
13
|
+
|
|
3
14
|
## 0.3.2 - 2026-05-04
|
|
4
15
|
|
|
5
16
|
- Fix Flatpak system-wide routing by requesting PipeWire manager access from the WirePlumber client.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mini-eq
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: Compact PipeWire system-wide parametric equalizer for Linux desktops.
|
|
5
5
|
Author: bhack
|
|
6
6
|
License-Expression: GPL-3.0-or-later
|
|
@@ -68,6 +68,8 @@ libebur128 is available, the monitor can also show live LUFS loudness.
|
|
|
68
68
|
compatibility layer.
|
|
69
69
|
- Per-output preset links for automatically using different saved presets with
|
|
70
70
|
headphones, speakers, HDMI, and other outputs.
|
|
71
|
+
- Optional background mode keeps the EQ active after closing the window, with a
|
|
72
|
+
separate Start at Login preference.
|
|
71
73
|
- Optional GNOME Shell extension for quick panel access to routing, EQ,
|
|
72
74
|
analyzer status, presets, and output preset links.
|
|
73
75
|
- Equalizer APO preset import from the UI or `--import-apo`, including
|
|
@@ -25,6 +25,8 @@ libebur128 is available, the monitor can also show live LUFS loudness.
|
|
|
25
25
|
compatibility layer.
|
|
26
26
|
- Per-output preset links for automatically using different saved presets with
|
|
27
27
|
headphones, speakers, HDMI, and other outputs.
|
|
28
|
+
- Optional background mode keeps the EQ active after closing the window, with a
|
|
29
|
+
separate Start at Login preference.
|
|
28
30
|
- Optional GNOME Shell extension for quick panel access to routing, EQ,
|
|
29
31
|
analyzer status, presets, and output preset links.
|
|
30
32
|
- Equalizer APO preset import from the UI or `--import-apo`, including
|
|
@@ -34,11 +34,11 @@
|
|
|
34
34
|
</description>
|
|
35
35
|
<screenshots>
|
|
36
36
|
<screenshot type="default">
|
|
37
|
-
<image>https://raw.githubusercontent.com/bhack/mini-eq/v0.
|
|
37
|
+
<image>https://raw.githubusercontent.com/bhack/mini-eq/v0.4.0/docs/screenshots/mini-eq.png</image>
|
|
38
38
|
<caption>Adjust sound output with equalizer controls</caption>
|
|
39
39
|
</screenshot>
|
|
40
40
|
<screenshot>
|
|
41
|
-
<image>https://raw.githubusercontent.com/bhack/mini-eq/v0.
|
|
41
|
+
<image>https://raw.githubusercontent.com/bhack/mini-eq/v0.4.0/docs/screenshots/mini-eq-dark.png</image>
|
|
42
42
|
<caption>Use the equalizer with dark style</caption>
|
|
43
43
|
</screenshot>
|
|
44
44
|
</screenshots>
|
|
@@ -46,6 +46,15 @@
|
|
|
46
46
|
<url type="bugtracker">https://github.com/bhack/mini-eq/issues</url>
|
|
47
47
|
<url type="vcs-browser">https://github.com/bhack/mini-eq</url>
|
|
48
48
|
<releases>
|
|
49
|
+
<release version="0.4.0" date="2026-05-05">
|
|
50
|
+
<description>
|
|
51
|
+
<ul>
|
|
52
|
+
<li>Add background mode and Start at Login support.</li>
|
|
53
|
+
<li>Keep GNOME event sounds and notifications out of system-wide EQ routing.</li>
|
|
54
|
+
<li>Add Shell extension controls for showing and quitting the background app.</li>
|
|
55
|
+
</ul>
|
|
56
|
+
</description>
|
|
57
|
+
</release>
|
|
49
58
|
<release version="0.3.2" date="2026-05-04">
|
|
50
59
|
<description>
|
|
51
60
|
<ul>
|
|
@@ -68,6 +68,11 @@ extension source changed since the relevant release tag. If it reports that an
|
|
|
68
68
|
upload may be needed, test the extension and upload the generated zip to
|
|
69
69
|
extensions.gnome.org after the release is ready.
|
|
70
70
|
|
|
71
|
+
The preflight also prints a Flatpak background portal smoke notice when
|
|
72
|
+
background mode, Start at Login, hidden-window lifecycle, Shell control, or
|
|
73
|
+
Flatpak integration paths changed. That notice is change-aware; do the manual
|
|
74
|
+
portal smoke only for releases that touch those paths.
|
|
75
|
+
|
|
71
76
|
## Check Locally
|
|
72
77
|
|
|
73
78
|
```bash
|
|
@@ -118,9 +123,32 @@ crash and streams are restored:
|
|
|
118
123
|
flatpak run io.github.bhack.mini-eq//master --auto-route
|
|
119
124
|
```
|
|
120
125
|
|
|
126
|
+
For background portal changes, run one clean-permission Flatpak smoke in a real
|
|
127
|
+
GNOME session:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
flatpak permission-remove background background io.github.bhack.mini-eq || true
|
|
131
|
+
flatpak run --command=flathub-build org.flatpak.Builder --install io.github.bhack.mini-eq.yaml
|
|
132
|
+
flatpak run io.github.bhack.mini-eq//master
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Then enable **Keep Running in Background**, approve the portal prompt, enable
|
|
136
|
+
**Start at Login**, close the window, and confirm the app stays available from
|
|
137
|
+
the GNOME Shell extension. Use the Shell extension's **Show Mini EQ** and
|
|
138
|
+
**Quit Mini EQ** actions to verify hidden-window recovery and full exit.
|
|
139
|
+
|
|
121
140
|
There is also an experimental non-blocking GitHub Actions path for this check:
|
|
122
|
-
manually dispatch the `CI` workflow with `flatpak_runtime_smoke=true
|
|
123
|
-
|
|
141
|
+
manually dispatch the `CI` workflow with `flatpak_runtime_smoke=true` and, when
|
|
142
|
+
iterating only on the smoke harness, `smoke_only=true`. For quick harness
|
|
143
|
+
iterations against the published Flathub app, use `flatpak_runtime_build=false`,
|
|
144
|
+
`flatpak_runtime_install_remote=true`, and the default blank
|
|
145
|
+
`flatpak_runtime_app_ref` so the harness runs the installed Flathub ref. Set
|
|
146
|
+
`flatpak_runtime_expected_version` when using the published app, because Flathub
|
|
147
|
+
metadata can lag after an update. Leave `flatpak_runtime_build=true` for any
|
|
148
|
+
release check that must test current source or the local manifest. Use hosted
|
|
149
|
+
smoke as the validation for harness-only CI changes and as extra release signal;
|
|
150
|
+
keep the local runtime smoke as the release check when app/runtime routing
|
|
151
|
+
behavior changed.
|
|
124
152
|
|
|
125
153
|
## Build
|
|
126
154
|
|
|
@@ -170,7 +198,17 @@ documentation.
|
|
|
170
198
|
|
|
171
199
|
## Security
|
|
172
200
|
|
|
173
|
-
Before publishing release artifacts, run
|
|
201
|
+
Before publishing release artifacts, run the full preflight. Its focused leak
|
|
202
|
+
scan covers `HEAD`, tracked worktree changes, and untracked non-ignored text
|
|
203
|
+
files, so run it again after any release-process edits:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
python3 tools/release_preflight.py
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
If reproducing the scan manually, check committed history, the tracked worktree,
|
|
210
|
+
and untracked non-ignored files. Do not rely on a `HEAD`-only scan before
|
|
211
|
+
committing release files:
|
|
174
212
|
|
|
175
213
|
```bash
|
|
176
214
|
git rev-list --count HEAD
|
|
@@ -182,6 +220,14 @@ git grep -n -I -E "$leak_pattern" HEAD -- . \
|
|
|
182
220
|
':(exclude)AGENTS.md' \
|
|
183
221
|
':(exclude)docs/release.md' \
|
|
184
222
|
':(exclude)tools/release_preflight.py'
|
|
223
|
+
git grep -n -I -E "$leak_pattern" -- . \
|
|
224
|
+
':(exclude)*.png' \
|
|
225
|
+
':(exclude)AGENTS.md' \
|
|
226
|
+
':(exclude)docs/release.md' \
|
|
227
|
+
':(exclude)tools/release_preflight.py'
|
|
228
|
+
git ls-files --others --exclude-standard -z -- . \
|
|
229
|
+
| grep -z -v -E '(^|/)(AGENTS\.md|docs/release\.md|tools/release_preflight\.py)$|\.png$' \
|
|
230
|
+
| xargs -0 -r grep -n -I -E "$leak_pattern" --
|
|
185
231
|
```
|
|
186
232
|
|
|
187
233
|
Keep these GitHub security features enabled in Settings > Advanced Security:
|
|
@@ -69,6 +69,7 @@ class MiniEqIndicator extends PanelMenu.Button {
|
|
|
69
69
|
this._running = false;
|
|
70
70
|
this._routed = false;
|
|
71
71
|
this._eqEnabled = false;
|
|
72
|
+
this._capabilities = new Set();
|
|
72
73
|
this.visible = false;
|
|
73
74
|
|
|
74
75
|
const box = new St.BoxLayout({
|
|
@@ -119,6 +120,11 @@ class MiniEqIndicator extends PanelMenu.Button {
|
|
|
119
120
|
});
|
|
120
121
|
this.menu.addMenuItem(openItem);
|
|
121
122
|
|
|
123
|
+
this._quitItem = new PopupMenu.PopupMenuItem(_('Quit Mini EQ'));
|
|
124
|
+
this._quitItem.visible = false;
|
|
125
|
+
this._quitItem.connect('activate', () => this._quitMiniEq());
|
|
126
|
+
this.menu.addMenuItem(this._quitItem);
|
|
127
|
+
|
|
122
128
|
this._signalId = Gio.DBus.session.signal_subscribe(
|
|
123
129
|
BUS_NAME,
|
|
124
130
|
INTERFACE_NAME,
|
|
@@ -292,6 +298,16 @@ class MiniEqIndicator extends PanelMenu.Button {
|
|
|
292
298
|
this._call('PresentWindow', null, null, () => {});
|
|
293
299
|
}
|
|
294
300
|
|
|
301
|
+
_quitMiniEq() {
|
|
302
|
+
this._call('Quit', null, null, () => {
|
|
303
|
+
this._setDisconnectedState();
|
|
304
|
+
this._scheduleRefresh(500);
|
|
305
|
+
}, () => {
|
|
306
|
+
this._quitItem.visible = false;
|
|
307
|
+
this._scheduleRefresh(500);
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
|
|
295
311
|
_showWindow(event) {
|
|
296
312
|
const app = Shell.AppSystem.get_default().lookup_app(APP_DESKTOP_ID);
|
|
297
313
|
const windows = app?.get_windows().filter(window => !window.skip_taskbar) ?? [];
|
|
@@ -322,6 +338,9 @@ class MiniEqIndicator extends PanelMenu.Button {
|
|
|
322
338
|
const routed = Boolean(unpackValue(state.routed));
|
|
323
339
|
const presetName = unpackValue(state.preset_name) || _('Current State');
|
|
324
340
|
const outputPresetName = unpackValue(state.output_preset_name) || '';
|
|
341
|
+
const capabilities = unpackValue(state.capabilities) || [];
|
|
342
|
+
this._capabilities = new Set(Array.isArray(capabilities) ? capabilities : []);
|
|
343
|
+
const canQuit = this._capabilities.has('quit');
|
|
325
344
|
|
|
326
345
|
this._running = running;
|
|
327
346
|
this._routed = routed;
|
|
@@ -345,12 +364,14 @@ class MiniEqIndicator extends PanelMenu.Button {
|
|
|
345
364
|
this._presetsItem.label.text = running ? _('Preset: %s').format(presetName) : _('Presets');
|
|
346
365
|
this._statusItem.label.text = this._statusText(running, routed, eqEnabled);
|
|
347
366
|
this._outputPresetItem.label.text = this._outputPresetText(running, outputPresetName);
|
|
367
|
+
this._quitItem.visible = running && canQuit;
|
|
348
368
|
}
|
|
349
369
|
|
|
350
370
|
_setDisconnectedState() {
|
|
351
371
|
this._running = false;
|
|
352
372
|
this._routed = false;
|
|
353
373
|
this._eqEnabled = false;
|
|
374
|
+
this._capabilities = new Set();
|
|
354
375
|
this.visible = false;
|
|
355
376
|
this._syncPanelStateStyle(false, false, false);
|
|
356
377
|
this._updating = true;
|
|
@@ -367,6 +388,7 @@ class MiniEqIndicator extends PanelMenu.Button {
|
|
|
367
388
|
this._presetsItem.label.text = _('Presets');
|
|
368
389
|
this._statusItem.label.text = _('Mini EQ is not running');
|
|
369
390
|
this._outputPresetItem.label.text = _('Output preset: None');
|
|
391
|
+
this._quitItem.visible = false;
|
|
370
392
|
this._setAnalyzerLevels([]);
|
|
371
393
|
this._setPresets([]);
|
|
372
394
|
}
|
|
@@ -11,8 +11,15 @@ gi.require_version("Adw", "1")
|
|
|
11
11
|
from gi.repository import Adw, Gio, GLib, GLibUnix
|
|
12
12
|
|
|
13
13
|
from .appearance import apply_appearance_preference, load_appearance_preference
|
|
14
|
+
from .background import (
|
|
15
|
+
load_background_mode,
|
|
16
|
+
load_start_at_login,
|
|
17
|
+
save_background_mode,
|
|
18
|
+
save_start_at_login,
|
|
19
|
+
set_background_status,
|
|
20
|
+
)
|
|
14
21
|
from .cli import parse_args
|
|
15
|
-
from .dbus_control import MiniEqDbusControl
|
|
22
|
+
from .dbus_control import MiniEqDbusControl, call_present_window
|
|
16
23
|
from .desktop_integration import APP_ICON_NAME, APP_ID, install_app_icon, install_desktop_integration
|
|
17
24
|
from .glib_utils import destroy_glib_source
|
|
18
25
|
from .instance import MiniEqAlreadyRunningError, MiniEqInstanceGuard
|
|
@@ -29,6 +36,8 @@ class MiniEqApplication(Adw.Application):
|
|
|
29
36
|
self.dbus_control: MiniEqDbusControl | None = None
|
|
30
37
|
self.signal_source_ids: list[int] = []
|
|
31
38
|
self.window_present_source_id = 0
|
|
39
|
+
self.background_mode = load_background_mode() or bool(getattr(args, "background", False))
|
|
40
|
+
self.start_at_login = load_start_at_login()
|
|
32
41
|
|
|
33
42
|
def do_startup(self) -> None:
|
|
34
43
|
Adw.Application.do_startup(self)
|
|
@@ -37,7 +46,7 @@ class MiniEqApplication(Adw.Application):
|
|
|
37
46
|
self.install_standard_actions()
|
|
38
47
|
self.dbus_control = MiniEqDbusControl(self)
|
|
39
48
|
self.dbus_control.register()
|
|
40
|
-
self.signal_source_ids = install_unix_signal_handlers(self.
|
|
49
|
+
self.signal_source_ids = install_unix_signal_handlers(self.quit_fully)
|
|
41
50
|
|
|
42
51
|
def install_standard_actions(self) -> None:
|
|
43
52
|
quit_action = Gio.SimpleAction.new("quit", None)
|
|
@@ -51,11 +60,7 @@ class MiniEqApplication(Adw.Application):
|
|
|
51
60
|
self.set_accels_for_action("app.close", ["<primary>w"])
|
|
52
61
|
|
|
53
62
|
def on_quit_action(self, _action: Gio.SimpleAction, _parameter: GLib.Variant | None) -> None:
|
|
54
|
-
|
|
55
|
-
self.window.close()
|
|
56
|
-
return
|
|
57
|
-
|
|
58
|
-
self.quit()
|
|
63
|
+
self.quit_fully()
|
|
59
64
|
|
|
60
65
|
def on_close_action(self, _action: Gio.SimpleAction, _parameter: GLib.Variant | None) -> None:
|
|
61
66
|
if self.window is not None and not self.window.ui_shutting_down:
|
|
@@ -65,12 +70,19 @@ class MiniEqApplication(Adw.Application):
|
|
|
65
70
|
self.quit()
|
|
66
71
|
|
|
67
72
|
def do_activate(self) -> None:
|
|
73
|
+
self.ensure_window(present=not bool(getattr(self.args, "background", False)))
|
|
74
|
+
|
|
75
|
+
def ensure_window(self, *, present: bool) -> None:
|
|
68
76
|
install_app_icon()
|
|
69
77
|
|
|
70
78
|
if self.window is not None:
|
|
71
79
|
if self.window.ui_shutting_down:
|
|
72
80
|
return
|
|
73
|
-
|
|
81
|
+
if present:
|
|
82
|
+
self.window.present_after_setup = True
|
|
83
|
+
self.window.set_visible(True)
|
|
84
|
+
self.window.present()
|
|
85
|
+
self.emit_control_state_changed()
|
|
74
86
|
self.window.schedule_post_present_setup()
|
|
75
87
|
return
|
|
76
88
|
|
|
@@ -90,10 +102,47 @@ class MiniEqApplication(Adw.Application):
|
|
|
90
102
|
self.controller = controller
|
|
91
103
|
self.window = MiniEqWindow(self, self.controller, self.args.auto_route)
|
|
92
104
|
self.window.set_icon_name(APP_ICON_NAME)
|
|
93
|
-
self.window.
|
|
94
|
-
self.window.present
|
|
105
|
+
self.window.present_after_setup = present
|
|
106
|
+
self.window.set_visible(present)
|
|
107
|
+
if present:
|
|
108
|
+
self.window.present()
|
|
95
109
|
self.window.schedule_post_present_setup()
|
|
96
|
-
|
|
110
|
+
if present:
|
|
111
|
+
self.window_present_source_id = GLib.idle_add(self.on_window_present_idle)
|
|
112
|
+
else:
|
|
113
|
+
self.update_background_status()
|
|
114
|
+
self.emit_control_state_changed()
|
|
115
|
+
|
|
116
|
+
def present_main_window(self) -> None:
|
|
117
|
+
self.ensure_window(present=True)
|
|
118
|
+
|
|
119
|
+
def quit_fully(self) -> None:
|
|
120
|
+
if self.window is not None and not self.window.ui_shutting_down:
|
|
121
|
+
self.window.begin_close_request_shutdown(force_quit=True)
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
self.quit()
|
|
125
|
+
|
|
126
|
+
def set_background_mode(self, enabled: bool) -> None:
|
|
127
|
+
self.background_mode = bool(enabled)
|
|
128
|
+
save_background_mode(self.background_mode)
|
|
129
|
+
self.emit_control_state_changed()
|
|
130
|
+
|
|
131
|
+
def set_start_at_login(self, enabled: bool) -> None:
|
|
132
|
+
self.start_at_login = bool(enabled)
|
|
133
|
+
save_start_at_login(self.start_at_login)
|
|
134
|
+
self.emit_control_state_changed()
|
|
135
|
+
|
|
136
|
+
def update_background_status(self) -> None:
|
|
137
|
+
if self.controller is not None and self.controller.routed and self.controller.eq_enabled:
|
|
138
|
+
message = "System-wide EQ active"
|
|
139
|
+
else:
|
|
140
|
+
message = "Mini EQ ready"
|
|
141
|
+
|
|
142
|
+
try:
|
|
143
|
+
set_background_status(message)
|
|
144
|
+
except Exception:
|
|
145
|
+
pass
|
|
97
146
|
|
|
98
147
|
def on_window_present_idle(self) -> bool:
|
|
99
148
|
self.window_present_source_id = 0
|
|
@@ -104,6 +153,8 @@ class MiniEqApplication(Adw.Application):
|
|
|
104
153
|
return False
|
|
105
154
|
|
|
106
155
|
def emit_control_state_changed(self) -> None:
|
|
156
|
+
if self.window is not None and not self.window.get_visible():
|
|
157
|
+
self.update_background_status()
|
|
107
158
|
if self.dbus_control is not None:
|
|
108
159
|
self.dbus_control.emit_state_changed()
|
|
109
160
|
|
|
@@ -197,6 +248,15 @@ def run_from_args(args: Namespace) -> int:
|
|
|
197
248
|
try:
|
|
198
249
|
instance_guard = MiniEqInstanceGuard.acquire()
|
|
199
250
|
except MiniEqAlreadyRunningError as exc:
|
|
251
|
+
if getattr(args, "background", False):
|
|
252
|
+
return 0
|
|
253
|
+
|
|
254
|
+
try:
|
|
255
|
+
call_present_window()
|
|
256
|
+
return 0
|
|
257
|
+
except Exception:
|
|
258
|
+
pass
|
|
259
|
+
|
|
200
260
|
print(str(exc), file=sys.stderr)
|
|
201
261
|
return 2
|
|
202
262
|
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
-
import json
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
from typing import Final
|
|
6
5
|
|
|
@@ -10,7 +9,8 @@ gi.require_version("Adw", "1")
|
|
|
10
9
|
|
|
11
10
|
from gi.repository import Adw
|
|
12
11
|
|
|
13
|
-
from .
|
|
12
|
+
from .settings import load_settings, update_setting
|
|
13
|
+
from .settings import settings_path as _settings_path
|
|
14
14
|
|
|
15
15
|
APPEARANCE_SYSTEM: Final = "system"
|
|
16
16
|
APPEARANCE_LIGHT: Final = "light"
|
|
@@ -29,40 +29,15 @@ def normalize_appearance(value: object) -> str:
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
def settings_path() -> Path:
|
|
32
|
-
return
|
|
32
|
+
return _settings_path()
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
def load_appearance_preference() -> str:
|
|
36
|
-
|
|
37
|
-
if not path.is_file():
|
|
38
|
-
return DEFAULT_APPEARANCE
|
|
39
|
-
|
|
40
|
-
try:
|
|
41
|
-
payload = json.loads(path.read_text(encoding="utf-8"))
|
|
42
|
-
except (OSError, json.JSONDecodeError):
|
|
43
|
-
return DEFAULT_APPEARANCE
|
|
44
|
-
|
|
45
|
-
if not isinstance(payload, dict):
|
|
46
|
-
return DEFAULT_APPEARANCE
|
|
47
|
-
|
|
48
|
-
return normalize_appearance(payload.get(APPEARANCE_KEY))
|
|
36
|
+
return normalize_appearance(load_settings().get(APPEARANCE_KEY))
|
|
49
37
|
|
|
50
38
|
|
|
51
39
|
def save_appearance_preference(appearance: str) -> None:
|
|
52
|
-
|
|
53
|
-
payload: dict[str, object] = {}
|
|
54
|
-
|
|
55
|
-
if path.is_file():
|
|
56
|
-
try:
|
|
57
|
-
loaded = json.loads(path.read_text(encoding="utf-8"))
|
|
58
|
-
except (OSError, json.JSONDecodeError):
|
|
59
|
-
loaded = {}
|
|
60
|
-
if isinstance(loaded, dict):
|
|
61
|
-
payload = loaded
|
|
62
|
-
|
|
63
|
-
payload[APPEARANCE_KEY] = normalize_appearance(appearance)
|
|
64
|
-
path.parent.mkdir(parents=True, exist_ok=True)
|
|
65
|
-
path.write_text(json.dumps(payload, indent=2) + "\n", encoding="utf-8")
|
|
40
|
+
update_setting(APPEARANCE_KEY, normalize_appearance(appearance))
|
|
66
41
|
|
|
67
42
|
|
|
68
43
|
def color_scheme_for_appearance(appearance: str):
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024" role="img" aria-label="Mini EQ">
|
|
2
|
-
<g transform="translate(512
|
|
2
|
+
<g transform="translate(512 514) scale(1.08) translate(-512 -512)">
|
|
3
3
|
<rect x="162" y="146" width="700" height="732" rx="118" fill="#38545f" stroke="#8bd2dc" stroke-width="24"/>
|
|
4
4
|
<path d="M280 178h464c64 0 86 22 86 86v86c-76-48-180-72-318-72s-242 24-318 72v-86c0-64 22-86 86-86Z" fill="#5f7c86" opacity="0.24"/>
|
|
5
5
|
<rect x="194" y="180" width="636" height="664" rx="92" fill="none" stroke="#18303a" stroke-width="8" opacity="0.60"/>
|