diff --git a/src-tauri/src/audio.rs b/src-tauri/src/audio.rs index 2046d898..3be25d25 100644 --- a/src-tauri/src/audio.rs +++ b/src-tauri/src/audio.rs @@ -2076,10 +2076,28 @@ fn open_stream_for_device_and_rate(device_name: Option<&str>, desired_rate: u32) let host = rodio::cpal::default_host(); - // Resolve the target device: named device first, fall back to system default. - let device = device_name.and_then(|name| { + // Resolve the target device: explicit name first, then (on Linux) prefer + // a "pipewire" or "pulse" ALSA alias before falling back to cpal's system + // default. On PipeWire-based distros the raw ALSA `default` alias can + // route to a null sink at app-start (issue #234 on Debian 13): the stream + // opens cleanly, progress ticks run, no audio reaches the user. The + // named-alias path goes through pipewire-alsa's real sink and just works. + // On systems where neither alias exists (pure ALSA, macOS, Windows), + // `find_by_name` returns None and we drop through to `default_output_device` + // unchanged — no regression. + let find_by_name = |name: &str| -> Option<_> { host.output_devices().ok()?.find(|d| d.name().ok().as_deref() == Some(name)) - }).or_else(|| host.default_output_device()); + }; + + let device = device_name + .and_then(find_by_name) + .or_else(|| { + #[cfg(target_os = "linux")] + { find_by_name("pipewire").or_else(|| find_by_name("pulse")) } + #[cfg(not(target_os = "linux"))] + { None } + }) + .or_else(|| host.default_output_device()); if let Some(device) = device { if desired_rate > 0 { diff --git a/src/pages/Settings.tsx b/src/pages/Settings.tsx index 9aede1c7..8236b535 100644 --- a/src/pages/Settings.tsx +++ b/src/pages/Settings.tsx @@ -211,6 +211,57 @@ const CONTRIBUTORS = [ 'WebView2 idle hooks when Tauri windows are hidden — Windows GPU and compositor mitigation (PR #273)', ], }, + { + github: 'Psychotoxical', + since: '1.0.0', + contributions: [ + 'Initial app scaffold — Tauri v2 + React + Zustand + Subsonic protocol, multi-server auth (v1.0)', + 'Rust/rodio audio engine replacing Howler.js (v1.2)', + 'Waveform seekbar, MilkDrop visualizer, EQ bars (v1.3)', + '10-band parametric equalizer with per-theme UI (v1.5)', + 'Replay Gain, Crossfade, Download Folder Modal (v1.6)', + 'Last.fm scrobbling, Similar Artists, Statistics page (v1.7)', + 'TooltipPortal + CustomSelect portal-based UI primitives (v1.7)', + 'Keybindings system + font picker (v1.9)', + 'Lyrics system with LRCLIB integration (v1.12)', + 'Queue management overhaul + DnD (v1.22)', + 'Advanced Search + Genre Mix overhaul (v1.23)', + 'Playlist Management — create/edit/cover upload, drag reorder (v1.24)', + 'Functional tray icon, Minimize to Tray, Sidebar customization (v1.25)', + 'Bulk Select, Song Info modal, Recently Played (v1.26)', + 'In-App Auto-Update + Configurable Home (v1.27)', + 'Infinite Queue + Start Radio + single-click play (v1.28)', + 'Internet Radio with fast-start, ICY metadata support (v1.29)', + 'Discord Rich Presence, offline bulk download, artist images, lazy loading (v1.30)', + 'AutoEQ integration, resizable tracklist columns (v1.31)', + 'Genre browser with filter + FLAC seek fix (v1.20)', + 'Fullscreen Player with dynamic accent color + mesh blobs (v1.34)', + 'Bit-perfect hi-res playback + underrun hardening (v1.34)', + 'Fullscreen lyrics overlay with FsArt crossfade (v1.34.1)', + 'Offline Mode (beta) + MPRIS seek (v1.18)', + 'NSIS Windows installer (v1.19)', + 'WCAG contrast audits across 60+ themes (v1.17-v1.34)', + 'Custom Linux title bar with now-playing display (v1.34)', + 'Device Sync — fixed cross-OS naming scheme + playlist folders (v1.40)', + 'macOS signing + notarization + Tauri auto-updater (v1.40)', + 'Mini player — floating window, custom titlebar, queue DnD, persistent geometry, keyboard shortcut, WebView2 lifecycle fix (PR #162, v1.42.x)', + '67 themes across 8 groups (Mediaplayer, OS, Games, Movies, Series, Social Media, OSS Classics, Psysonic)', + 'Admin-gated User Management tab with per-user library assignment (PR #222)', + 'Comprehensive mobile UI overhaul (PR #238)', + 'Runtime log levels and debug log export (PR #241)', + 'ReplayGain Auto mode — picks track vs album gain from queue context (PR #242)', + 'Now-Playing Info tab with artist bio, song credits, Bandsintown tour dates (PR #244)', + 'Performance suite — search cover cache, DeviceSync N+1, Albums prefetch, Lyrics IDB, bundle splitting, Artists memo, Genres pagination (PRs #245-#251)', + 'Artist page — user-configurable section visibility and order (PR #254)', + 'Album enqueue via cover hover, context menu, multi-select toolbar (PR #256)', + 'Settings refactor — thematic tab regroup, accordion sub-sections, in-page search (PR #259)', + 'Navidrome admin API hardening (PR #260)', + 'Library deep links (psysonic2 scheme) — paste track/album/artist/queue (PR #261)', + 'Now-Playing redesign as info dashboard + draggable widget cards (PRs #266, #267)', + 'Sleep timer — circular ring + in-button countdown (PR #272)', + 'Streaming seek UI freeze + snapback fix (PR #236)', + ], + }, ] as const; const MAINTAINERS = [ diff --git a/src/styles/components.css b/src/styles/components.css index 9bd9ffdd..4e402f21 100644 --- a/src/styles/components.css +++ b/src/styles/components.css @@ -3247,6 +3247,20 @@ font-size: 12px; color: var(--text-secondary); line-height: 1.7; + list-style: none; +} +.contributor-card-list li { + position: relative; + padding-left: 14px; +} +.contributor-card-list li::before { + content: '•'; + position: absolute; + left: 0; + top: 0; + color: var(--accent); + font-weight: 700; + line-height: 1.7; } /* ── Datenschutz-Hinweis-Banner (z.B. oben im Integrations-Tab) ──────────── */