diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-20 15:56:26 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-20 15:56:26 -0500 |
| commit | a29769e0f46aa2e2b9ed3662d58d1395a665b5d5 (patch) | |
| tree | 72fb0a30c5c9207ebfc395b7886c223e0038da47 /scripts/normalize-notify-sounds.sh | |
| parent | 44ccab18d624d3f5b7acbe65f4ad5616247aad00 (diff) | |
| download | archsetup-a29769e0f46aa2e2b9ed3662d58d1395a665b5d5.tar.gz archsetup-a29769e0f46aa2e2b9ed3662d58d1395a665b5d5.zip | |
fix(sounds): make normalize-notify-sounds write atomically and clean up
The script re-encoded each notify sound with `cat "$tmp" > "$f"`, which truncates the target first -- a short or empty encode left a corrupt, repo-tracked sound file. The mktemp also had no trap, so an interrupted encode leaked a temp.
Now it resolves the real target with `readlink -f` (SOUND_DIR is usually the stow-symlinked ~/.local copy), stages the temp beside it, guards on a non-empty encode, and moves it into place. The mv is atomic on one filesystem and replaces the real file, so the stow symlink still points at it. An EXIT trap removes the in-flight temp when a failed encode aborts the run.
Diffstat (limited to 'scripts/normalize-notify-sounds.sh')
| -rwxr-xr-x | scripts/normalize-notify-sounds.sh | 26 |
1 files changed, 20 insertions, 6 deletions
diff --git a/scripts/normalize-notify-sounds.sh b/scripts/normalize-notify-sounds.sh index 72c4c33..7dffbbc 100755 --- a/scripts/normalize-notify-sounds.sh +++ b/scripts/normalize-notify-sounds.sh @@ -28,6 +28,12 @@ shopt -s nullglob files=("$SOUND_DIR"/*.ogg) (( ${#files[@]} )) || { echo "No .ogg files in $SOUND_DIR" >&2; exit 1; } +# Clean up the in-flight temp file on any exit (a failed encode under set -e +# aborts mid-loop, so the trap is what stops the temp from leaking). +tmp="" +cleanup() { [ -n "${tmp:-}" ] && rm -f "$tmp"; return 0; } +trap cleanup EXIT + for f in "${files[@]}"; do mean=$(ffmpeg -hide_banner -nostats -i "$f" -af volumedetect -f null /dev/null 2>&1 \ | grep -oP 'mean_volume: \K[-0-9.]+' || true) @@ -36,14 +42,22 @@ for f in "${files[@]}"; do continue fi gain=$(awk -v t="$TARGET_DB" -v m="$mean" 'BEGIN { printf "%.1f", t - m }') - tmp=$(mktemp --suffix=.ogg) + # Resolve the real target (SOUND_DIR is often the stow-symlinked ~/.local + # copy) and stage the temp beside it, so the mv is atomic on the same + # filesystem and replacing the real file leaves the stow symlink pointing + # at it. A truncate-in-place (cat > "$f") would have corrupted the tracked + # file if the encode produced a short or empty output. + target=$(readlink -f "$f") + tmp=$(mktemp --suffix=.ogg --tmpdir="$(dirname "$target")") ffmpeg -hide_banner -loglevel error -y -i "$f" \ -af "volume=${gain}dB" -c:a libvorbis -q:a 6 "$tmp" - # Write through the file rather than mv over it: when SOUND_DIR is the - # stow-symlinked ~/.local copy, mv would replace the symlink with a real - # file and decouple it from the repo. cat preserves the symlink target. - cat "$tmp" > "$f" - rm -f "$tmp" + if [ ! -s "$tmp" ]; then + echo "skip (empty re-encode): $f" >&2 + rm -f "$tmp"; tmp="" + continue + fi + mv -f "$tmp" "$target" + tmp="" printf "%-14s mean %7s dB gain %+6s dB -> target %s dB\n" \ "$(basename "$f")" "$mean" "$gain" "$TARGET_DB" done |
