feat(settings): add limit_quality_to_device setting
Add new audio setting to limit streaming quality based on device capabilities. When enabled (default: true), QBZ will avoid requesting tracks that exceed the device's max supported sample rate. This ensures bit-perfect playback by preventing the need to resample high-res tracks on devices that don't support them. - Add limit_quality_to_device field to AudioSettings - Add database migration for new column - Add Tauri command for frontend integration cc
This commit is contained in:
1 parent
da5ec2abcb
commit
be4786e6d3
2 files changed
+28
-1
No files matched your search
@@ -22,6 +22,10 @@ pub struct AudioSettings {
|
|||||||
pub stream_buffer_seconds: u8,
|
pub stream_buffer_seconds: u8,
|
||||||
/// When true, skip L1+L2 cache writes (streaming-only mode). Offline cache still works.
|
/// When true, skip L1+L2 cache writes (streaming-only mode). Offline cache still works.
|
||||||
pub streaming_only: bool,
|
pub streaming_only: bool,
|
||||||
|
/// When true, limit streaming quality to device's max supported sample rate.
|
||||||
|
/// This ensures bit-perfect playback by avoiding tracks that exceed device capabilities.
|
||||||
|
/// Default: true (recommended for bit-perfect setups)
|
||||||
|
pub limit_quality_to_device: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for AudioSettings {
|
impl Default for AudioSettings {
|
||||||
@@ -37,6 +41,7 @@ impl Default for AudioSettings {
|
|||||||
stream_first_track: true, // Enabled by default for faster playback start
|
stream_first_track: true, // Enabled by default for faster playback start
|
||||||
stream_buffer_seconds: 3, // 3 seconds initial buffer
|
stream_buffer_seconds: 3, // 3 seconds initial buffer
|
||||||
streaming_only: false, // Disabled by default (cache tracks for instant replay)
|
streaming_only: false, // Disabled by default (cache tracks for instant replay)
|
||||||
|
limit_quality_to_device: true, // Enabled by default for bit-perfect guarantee
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,6 +87,7 @@ impl AudioSettingsStore {
|
|||||||
let _ = conn.execute("ALTER TABLE audio_settings ADD COLUMN stream_first_track INTEGER DEFAULT 0", []);
|
let _ = conn.execute("ALTER TABLE audio_settings ADD COLUMN stream_first_track INTEGER DEFAULT 0", []);
|
||||||
let _ = conn.execute("ALTER TABLE audio_settings ADD COLUMN stream_buffer_seconds INTEGER DEFAULT 3", []);
|
let _ = conn.execute("ALTER TABLE audio_settings ADD COLUMN stream_buffer_seconds INTEGER DEFAULT 3", []);
|
||||||
let _ = conn.execute("ALTER TABLE audio_settings ADD COLUMN streaming_only INTEGER DEFAULT 0", []);
|
let _ = conn.execute("ALTER TABLE audio_settings ADD COLUMN streaming_only INTEGER DEFAULT 0", []);
|
||||||
|
let _ = conn.execute("ALTER TABLE audio_settings ADD COLUMN limit_quality_to_device INTEGER DEFAULT 1", []);
|
||||||
|
|
||||||
Ok(Self { conn })
|
Ok(Self { conn })
|
||||||
}
|
}
|
||||||
@@ -89,7 +95,7 @@ impl AudioSettingsStore {
|
|||||||
pub fn get_settings(&self) -> Result<AudioSettings, String> {
|
pub fn get_settings(&self) -> Result<AudioSettings, String> {
|
||||||
self.conn
|
self.conn
|
||||||
.query_row(
|
.query_row(
|
||||||
"SELECT output_device, exclusive_mode, dac_passthrough, preferred_sample_rate, backend_type, alsa_plugin, alsa_hardware_volume, stream_first_track, stream_buffer_seconds, streaming_only FROM audio_settings WHERE id = 1",
|
"SELECT output_device, exclusive_mode, dac_passthrough, preferred_sample_rate, backend_type, alsa_plugin, alsa_hardware_volume, stream_first_track, stream_buffer_seconds, streaming_only, limit_quality_to_device FROM audio_settings WHERE id = 1",
|
||||||
[],
|
[],
|
||||||
|row| {
|
|row| {
|
||||||
// Parse backend_type from JSON string
|
// Parse backend_type from JSON string
|
||||||
@@ -113,6 +119,7 @@ impl AudioSettingsStore {
|
|||||||
stream_first_track: row.get::<_, Option<i64>>(7)?.unwrap_or(0) != 0,
|
stream_first_track: row.get::<_, Option<i64>>(7)?.unwrap_or(0) != 0,
|
||||||
stream_buffer_seconds: row.get::<_, Option<i64>>(8)?.unwrap_or(3) as u8,
|
stream_buffer_seconds: row.get::<_, Option<i64>>(8)?.unwrap_or(3) as u8,
|
||||||
streaming_only: row.get::<_, Option<i64>>(9)?.unwrap_or(0) != 0,
|
streaming_only: row.get::<_, Option<i64>>(9)?.unwrap_or(0) != 0,
|
||||||
|
limit_quality_to_device: row.get::<_, Option<i64>>(10)?.unwrap_or(1) != 0,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -230,6 +237,16 @@ impl AudioSettingsStore {
|
|||||||
.map_err(|e| format!("Failed to set streaming only: {}", e))?;
|
.map_err(|e| format!("Failed to set streaming only: {}", e))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_limit_quality_to_device(&self, enabled: bool) -> Result<(), String> {
|
||||||
|
self.conn
|
||||||
|
.execute(
|
||||||
|
"UPDATE audio_settings SET limit_quality_to_device = ?1 WHERE id = 1",
|
||||||
|
params![enabled as i64],
|
||||||
|
)
|
||||||
|
.map_err(|e| format!("Failed to set limit quality to device: {}", e))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Thread-safe wrapper
|
/// Thread-safe wrapper
|
||||||
@@ -343,3 +360,12 @@ pub fn set_audio_streaming_only(
|
|||||||
let store = state.store.lock().map_err(|e| format!("Lock error: {}", e))?;
|
let store = state.store.lock().map_err(|e| format!("Lock error: {}", e))?;
|
||||||
store.set_streaming_only(enabled)
|
store.set_streaming_only(enabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub fn set_audio_limit_quality_to_device(
|
||||||
|
state: tauri::State<'_, AudioSettingsState>,
|
||||||
|
enabled: bool,
|
||||||
|
) -> Result<(), String> {
|
||||||
|
let store = state.store.lock().map_err(|e| format!("Lock error: {}", e))?;
|
||||||
|
store.set_limit_quality_to_device(enabled)
|
||||||
|
}
|
||||||
@@ -785,6 +785,7 @@ pub fn run() {
|
|||||||
config::audio_settings::set_audio_stream_first_track,
|
config::audio_settings::set_audio_stream_first_track,
|
||||||
config::audio_settings::set_audio_stream_buffer_seconds,
|
config::audio_settings::set_audio_stream_buffer_seconds,
|
||||||
config::audio_settings::set_audio_streaming_only,
|
config::audio_settings::set_audio_streaming_only,
|
||||||
|
config::audio_settings::set_audio_limit_quality_to_device,
|
||||||
// Audio backend commands
|
// Audio backend commands
|
||||||
commands::get_available_backends,
|
commands::get_available_backends,
|
||||||
commands::get_devices_for_backend,
|
commands::get_devices_for_backend,
|
||||||
|
|||||||
Reference in new issue
Block a user