fix: resolve all Rust warnings in qbz-nix crate
- Remove unused import TagExt in library/commands.rs - Remove unnecessary unsafe block in alsa_direct.rs - Fix value-never-read warnings in search.rs blacklist filtering - Handle unused Result from chromecast.disconnect() in lib.rs - Add #[allow(dead_code)] to unused but intentional API: - VECTOR_TTL_SECS constant (future use) - PipeWireBackend host field (stored for future use) - AlsaDirectStream is_playing field (future use) - CacheEntry track_id field (debug purposes) - CastSession app_id field (deserialized but unused) - ItunesAlbumResult struct (deserialized response) - ReleaseDetails struct (Discogs API response) - simple_hash function (utility for future use) - LrclibItem struct (lyrics API response) - AudioSpecs/AudioMetadata structs (future use) - Player visualizer_tap field (future feature) - Retry constants (future retry logic) - PlaybackEngine position/duration/is_alsa_direct methods Remaining warnings are in vendor/rodio (external code).
This commit is contained in:
1 parent
1540146df6
commit
678693d0c4
25 files changed
+58
-48
No files matched your search
@@ -12,6 +12,7 @@ use tokio::sync::Mutex;
|
||||
use super::sparse_vector::SparseVector;
|
||||
|
||||
/// TTL for vector entries (7 days)
|
||||
#[allow(dead_code)]
|
||||
const VECTOR_TTL_SECS: i64 = 7 * 24 * 60 * 60;
|
||||
|
||||
/// Shared state wrapper for Tauri
|
||||
|
||||
@@ -228,7 +228,7 @@ impl AlsaBackend {
|
||||
device
|
||||
.supported_output_configs()
|
||||
.ok()
|
||||
.and_then(|mut configs| {
|
||||
.and_then(|configs| {
|
||||
configs
|
||||
.max_by_key(|c| c.max_sample_rate().0)
|
||||
.map(|c| c.max_sample_rate().0)
|
||||
@@ -371,7 +371,7 @@ impl AlsaBackend {
|
||||
let max_sample_rate = device
|
||||
.supported_output_configs()
|
||||
.ok()
|
||||
.and_then(|mut configs| {
|
||||
.and_then(|configs| {
|
||||
configs
|
||||
.max_by_key(|c| c.max_sample_rate().0)
|
||||
.map(|c| c.max_sample_rate().0)
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
use alsa::pcm::{Access, Format, HwParams, PCM};
|
||||
#[cfg(target_os = "linux")]
|
||||
use alsa::{Direction, ValueOr};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
|
||||
/// Direct ALSA PCM stream for hw: devices
|
||||
pub struct AlsaDirectStream {
|
||||
pcm: Arc<Mutex<PCM>>,
|
||||
#[allow(dead_code)]
|
||||
is_playing: Arc<AtomicBool>,
|
||||
sample_rate: u32,
|
||||
channels: u16,
|
||||
@@ -122,7 +122,7 @@ impl AlsaDirectStream {
|
||||
/// Write audio samples to ALSA (auto-converts from i16 based on detected format)
|
||||
#[cfg(target_os = "linux")]
|
||||
pub fn write(&self, samples_i16: &[i16]) -> Result<(), String> {
|
||||
let mut pcm = self.pcm.lock().unwrap();
|
||||
let pcm = self.pcm.lock().unwrap();
|
||||
let frames = samples_i16.len() / self.channels as usize;
|
||||
|
||||
match self.format {
|
||||
@@ -218,7 +218,7 @@ impl AlsaDirectStream {
|
||||
}
|
||||
|
||||
// Use raw byte I/O for 3-byte packed format
|
||||
let io = unsafe { pcm.io_bytes() };
|
||||
let io = pcm.io_bytes();
|
||||
|
||||
match io.writei(&bytes) {
|
||||
Ok(written) => {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
//! - Creates stream using CPAL "pulse" or "pipewire" device
|
||||
//! - Does NOT change system default (only affects QBZ)
|
||||
|
||||
use super::backend::{AlsaPlugin, AudioBackend, AudioBackendType, AudioDevice, BackendConfig, BackendResult};
|
||||
use super::backend::{AudioBackend, AudioBackendType, AudioDevice, BackendConfig, BackendResult};
|
||||
use rodio::{
|
||||
cpal::{
|
||||
traits::{DeviceTrait, HostTrait},
|
||||
@@ -17,6 +17,7 @@ use rodio::{
|
||||
use std::process::Command;
|
||||
|
||||
pub struct PipeWireBackend {
|
||||
#[allow(dead_code)]
|
||||
host: rodio::cpal::Host,
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
//! Similar to PipeWire backend but for systems running PulseAudio only.
|
||||
//! Uses same approach: pactl + PULSE_SINK + CPAL "pulse" device.
|
||||
|
||||
use super::backend::{AlsaPlugin, AudioBackend, AudioBackendType, AudioDevice, BackendConfig, BackendResult};
|
||||
use super::backend::{AudioBackend, AudioBackendType, AudioDevice, BackendConfig, BackendResult};
|
||||
use super::pipewire_backend::PipeWireBackend;
|
||||
use rodio::{OutputStream, OutputStreamHandle};
|
||||
|
||||
|
||||
+1
@@ -13,6 +13,7 @@ use std::time::SystemTime;
|
||||
/// Entry metadata for tracking cache usage
|
||||
#[derive(Debug, Clone)]
|
||||
struct CacheEntry {
|
||||
#[allow(dead_code)]
|
||||
track_id: u64,
|
||||
size_bytes: u64,
|
||||
last_accessed: SystemTime,
|
||||
|
||||
@@ -47,6 +47,7 @@ pub struct CastApplication {
|
||||
}
|
||||
|
||||
struct CastSession {
|
||||
#[allow(dead_code)]
|
||||
app_id: String,
|
||||
session_id: String,
|
||||
transport_id: String,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
use tauri::State;
|
||||
|
||||
use crate::listenbrainz::{
|
||||
AdditionalInfo, ListenBrainzSharedState, ListenBrainzStatus, QueueStats, QueuedListen, UserInfo,
|
||||
AdditionalInfo, ListenBrainzSharedState, ListenBrainzStatus, QueuedListen, UserInfo,
|
||||
};
|
||||
|
||||
/// Get ListenBrainz connection status
|
||||
|
||||
@@ -384,7 +384,7 @@ fn release_to_resolved(release: &ReleaseResult) -> ResolvedRelease {
|
||||
|
||||
fn extract_relationships(artist: &ArtistFullResponse) -> ArtistRelationships {
|
||||
let mut members = Vec::new();
|
||||
let mut past_members = Vec::new();
|
||||
let past_members = Vec::new();
|
||||
let mut groups = Vec::new();
|
||||
let mut collaborators = Vec::new();
|
||||
|
||||
|
||||
@@ -568,7 +568,7 @@ fn extract_audio_format_from_header(data: &[u8]) -> Result<(u32, u16, u32), Stri
|
||||
use symphonia::core::probe::Hint;
|
||||
use symphonia::default::get_probe;
|
||||
|
||||
let cursor = Box::new(Cursor::new(data.to_vec())) as Box<dyn std::io::Read + Send + Sync>;
|
||||
let _cursor = Box::new(Cursor::new(data.to_vec())) as Box<dyn std::io::Read + Send + Sync>;
|
||||
// For probing, we need to create a MediaSource
|
||||
// Use a simple wrapper
|
||||
struct ProbeSource {
|
||||
|
||||
@@ -233,15 +233,11 @@ pub async fn search_all(
|
||||
});
|
||||
|
||||
// Apply blacklist filtering
|
||||
let mut filtered_tracks = 0;
|
||||
let mut filtered_artists = 0;
|
||||
let mut filtered_albums = 0;
|
||||
|
||||
// Filter albums from blacklisted artists
|
||||
let original_album_count = albums.items.len();
|
||||
let mut albums = albums;
|
||||
albums.items.retain(|album| !blacklist_state.is_blacklisted(album.artist.id));
|
||||
filtered_albums = original_album_count - albums.items.len();
|
||||
let filtered_albums = original_album_count - albums.items.len();
|
||||
if filtered_albums > 0 {
|
||||
albums.total = albums.total.saturating_sub(filtered_albums as u32);
|
||||
}
|
||||
@@ -255,7 +251,7 @@ pub async fn search_all(
|
||||
true
|
||||
}
|
||||
});
|
||||
filtered_tracks = original_track_count - tracks.items.len();
|
||||
let filtered_tracks = original_track_count - tracks.items.len();
|
||||
if filtered_tracks > 0 {
|
||||
tracks.total = tracks.total.saturating_sub(filtered_tracks as u32);
|
||||
}
|
||||
@@ -263,7 +259,7 @@ pub async fn search_all(
|
||||
// Filter blacklisted artists
|
||||
let original_artist_count = artists.items.len();
|
||||
artists.items.retain(|artist| !blacklist_state.is_blacklisted(artist.id));
|
||||
filtered_artists = original_artist_count - artists.items.len();
|
||||
let filtered_artists = original_artist_count - artists.items.len();
|
||||
if filtered_artists > 0 {
|
||||
artists.total = artists.total.saturating_sub(filtered_artists as u32);
|
||||
}
|
||||
|
||||
@@ -183,6 +183,7 @@ async fn search_itunes_by_term(title: &str, artist: &str) -> Option<String> {
|
||||
/// iTunes album lookup response
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[allow(dead_code)]
|
||||
struct ItunesAlbumResult {
|
||||
collection_id: Option<u64>,
|
||||
collection_view_url: Option<String>,
|
||||
@@ -200,7 +201,7 @@ struct ItunesAlbumLookupResponse {
|
||||
#[tauri::command]
|
||||
pub async fn share_album_songlink(
|
||||
upc: Option<String>,
|
||||
album_id: Option<String>,
|
||||
_album_id: Option<String>,
|
||||
title: Option<String>,
|
||||
artist: Option<String>,
|
||||
state: State<'_, AppState>,
|
||||
|
||||
@@ -46,6 +46,7 @@ pub struct DiscogsImageOption {
|
||||
|
||||
/// Release details from Discogs API (internal, for artwork)
|
||||
#[derive(Debug, Deserialize)]
|
||||
#[allow(dead_code)]
|
||||
struct ReleaseDetails {
|
||||
id: u64,
|
||||
title: String,
|
||||
|
||||
@@ -443,7 +443,7 @@ pub fn run() {
|
||||
// Disconnect Chromecast if connected (sends message through channel)
|
||||
if let Some(cast_state) = window.app_handle().try_state::<cast::CastState>() {
|
||||
log::info!("Disconnecting Chromecast on app exit");
|
||||
cast_state.chromecast.disconnect();
|
||||
let _ = cast_state.chromecast.disconnect();
|
||||
}
|
||||
|
||||
// Note: DLNA connection will be dropped when the app exits,
|
||||
|
||||
@@ -71,7 +71,7 @@ pub async fn library_add_folder(
|
||||
|
||||
log::info!("Folder network info: is_network={}, fs_type={:?}", is_network, fs_type);
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
let id = db.add_folder_with_network_info(&path, is_network, fs_type.as_deref())
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
@@ -88,7 +88,7 @@ pub async fn library_remove_folder(
|
||||
) -> Result<(), String> {
|
||||
log::info!("Command: library_remove_folder {}", path);
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
db.remove_folder(&path).map_err(|e| e.to_string())?;
|
||||
db.delete_tracks_in_folder(&path).map_err(|e| e.to_string())?;
|
||||
Ok(())
|
||||
@@ -109,7 +109,7 @@ pub async fn library_cleanup_missing_files(
|
||||
) -> Result<CleanupResult, String> {
|
||||
log::info!("Command: library_cleanup_missing_files");
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
|
||||
// Get all track paths
|
||||
let tracks = db.get_all_track_paths().map_err(|e| e.to_string())?;
|
||||
@@ -249,7 +249,7 @@ pub async fn library_clear_thumbnails_cache() -> Result<u64, String> {
|
||||
pub async fn library_get_folders(state: State<'_, LibraryState>) -> Result<Vec<String>, String> {
|
||||
log::info!("Command: library_get_folders");
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
db.get_folders().map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
@@ -261,7 +261,7 @@ pub async fn library_get_folders_with_metadata(
|
||||
) -> Result<Vec<LibraryFolder>, String> {
|
||||
log::info!("Command: library_get_folders_with_metadata");
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
let mut folders = db.get_folders_with_metadata().map_err(|e| e.to_string())?;
|
||||
|
||||
// Refresh network detection for folders without user override
|
||||
@@ -316,7 +316,7 @@ pub async fn library_get_folder(
|
||||
) -> Result<Option<LibraryFolder>, String> {
|
||||
log::info!("Command: library_get_folder {}", id);
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
db.get_folder_by_id(id).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ pub async fn library_update_folder_settings(
|
||||
) -> Result<LibraryFolder, String> {
|
||||
log::info!("Command: library_update_folder_settings {} alias={:?} enabled={}", id, alias, enabled);
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
db.update_folder_settings(
|
||||
id,
|
||||
alias.as_deref(),
|
||||
@@ -357,7 +357,7 @@ pub async fn library_set_folder_enabled(
|
||||
) -> Result<(), String> {
|
||||
log::info!("Command: library_set_folder_enabled {} enabled={}", id, enabled);
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
db.set_folder_enabled(id, enabled).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
@@ -379,7 +379,7 @@ pub async fn library_update_folder_path(
|
||||
return Err("The selected path is not a folder".to_string());
|
||||
}
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
db.update_folder_path(id, &new_path).map_err(|e| e.to_string())?;
|
||||
|
||||
// Check if it's a network folder and update network info
|
||||
@@ -691,7 +691,7 @@ async fn process_cue_file(cue_path: &Path, state: &State<'_, LibraryState>) -> R
|
||||
}
|
||||
|
||||
// Insert tracks
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
let group_key = tracks
|
||||
.first()
|
||||
.map(|track| track.album_group_key.clone())
|
||||
@@ -1022,7 +1022,7 @@ pub async fn library_get_albums(
|
||||
.map(|s| s.show_in_library)
|
||||
.unwrap_or(false);
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
|
||||
// Use optimized SQL-based filtering instead of N+1 query pattern
|
||||
let albums = db.get_albums_with_full_filter(
|
||||
@@ -1042,7 +1042,7 @@ pub async fn library_get_album_tracks(
|
||||
) -> Result<Vec<LocalTrack>, String> {
|
||||
log::info!("Command: library_get_album_tracks {}", album_group_key);
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
db.get_album_tracks(&album_group_key)
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
@@ -1063,7 +1063,7 @@ pub async fn library_get_artists(
|
||||
.map(|s| s.show_in_library)
|
||||
.unwrap_or(false);
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
|
||||
// Use optimized SQL-based filtering instead of N+1 query pattern
|
||||
let artists = db.get_artists_with_filter(
|
||||
@@ -1093,7 +1093,7 @@ pub async fn library_search(
|
||||
.map(|s| s.show_in_library)
|
||||
.unwrap_or(false);
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
|
||||
// Use optimized SQL-based filtering
|
||||
// limit = 0 means no limit (fetch all tracks)
|
||||
@@ -1112,7 +1112,7 @@ pub async fn library_search(
|
||||
pub async fn library_get_stats(state: State<'_, LibraryState>) -> Result<LibraryStats, String> {
|
||||
log::info!("Command: library_get_stats");
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
db.get_stats().map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
@@ -1120,7 +1120,7 @@ pub async fn library_get_stats(state: State<'_, LibraryState>) -> Result<Library
|
||||
pub async fn library_clear(state: State<'_, LibraryState>) -> Result<(), String> {
|
||||
log::info!("Command: library_clear");
|
||||
|
||||
let mut db = state.db.lock().await;
|
||||
let db = state.db.lock().await;
|
||||
db.clear_all_tracks().map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
@@ -1893,7 +1893,7 @@ pub async fn library_write_album_metadata_to_files(
|
||||
let write_result = tokio::task::spawn_blocking({
|
||||
let request = request.clone();
|
||||
move || -> Result<(), String> {
|
||||
use lofty::{Accessor, AudioFile, ItemKey, Tag, TagExt, TaggedFileExt, TagType};
|
||||
use lofty::{Accessor, AudioFile, ItemKey, Tag, TaggedFileExt};
|
||||
|
||||
// Ensure we only write each file once.
|
||||
let mut by_file: HashMap<String, &LibraryAlbumTrackMetadataUpdate> = HashMap::new();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//! Metadata extraction for audio files
|
||||
|
||||
use lofty::{Accessor, AudioFile, ItemKey, MimeType, Probe, TaggedFileExt};
|
||||
use lofty::{Accessor, AudioFile, ItemKey, Probe, TaggedFileExt};
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
@@ -467,6 +467,7 @@ impl MetadataExtractor {
|
||||
}
|
||||
|
||||
/// Simple hash function for generating filenames
|
||||
#[allow(dead_code)]
|
||||
fn simple_hash(s: &str) -> u64 {
|
||||
let mut hash: u64 = 5381;
|
||||
for byte in s.bytes() {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
//!
|
||||
//! SQLite-based queue for offline listens and token persistence
|
||||
|
||||
use rusqlite::{params, Connection, OptionalExtension};
|
||||
use rusqlite::{params, Connection};
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
use std::time::{SystemTime, UNIX_EPOCH};
|
||||
|
||||
@@ -16,6 +16,7 @@ pub struct LyricsData {
|
||||
|
||||
#[derive(Debug, Clone, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
#[allow(dead_code)]
|
||||
struct LrclibItem {
|
||||
#[serde(default)]
|
||||
pub track_name: String,
|
||||
|
||||
@@ -11,7 +11,7 @@ use std::sync::{
|
||||
Arc, Mutex,
|
||||
};
|
||||
use std::thread;
|
||||
use tauri::{AppHandle, Emitter, Manager};
|
||||
use tauri::{AppHandle, Emitter};
|
||||
use serde::Serialize;
|
||||
|
||||
/// Track metadata for media controls
|
||||
|
||||
@@ -6,8 +6,7 @@ use tauri::{AppHandle, Emitter, State};
|
||||
use crate::api::models::Quality;
|
||||
use crate::AppState;
|
||||
|
||||
use crate::offline_cache::path_validator::{self, PathValidationResult};
|
||||
use crate::offline_cache::{OfflineCacheDb, OfflineCacheState};
|
||||
use crate::offline_cache::OfflineCacheState;
|
||||
use crate::offline_cache::metadata::{fetch_complete_metadata, write_flac_tags, embed_artwork, organize_cached_file, save_album_artwork};
|
||||
use super::{
|
||||
CachedTrackInfo, OfflineCacheStats, OfflineCacheStatus,
|
||||
|
||||
@@ -22,7 +22,7 @@ use std::sync::mpsc::{self, Sender, RecvTimeoutError};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
use rodio::{Decoder, OutputStream, Sink, Source};
|
||||
use rodio::{Decoder, OutputStream, Source};
|
||||
use rodio::buffer::SamplesBuffer;
|
||||
use rodio::decoder::Mp4Type;
|
||||
use rodio::cpal::traits::{DeviceTrait, HostTrait};
|
||||
@@ -110,6 +110,7 @@ impl Seek for CursorMediaSource {
|
||||
}
|
||||
|
||||
/// Audio specifications extracted from decoded audio
|
||||
#[allow(dead_code)]
|
||||
struct AudioSpecs {
|
||||
samples: SamplesBuffer<i16>,
|
||||
sample_rate: u32,
|
||||
@@ -201,12 +202,14 @@ fn is_isomp4(data: &[u8]) -> bool {
|
||||
/// Extract audio metadata (sample rate, channels) without full decode.
|
||||
/// This is much faster than decode_with_symphonia as it only reads headers.
|
||||
/// Audio metadata extracted from file headers
|
||||
#[allow(dead_code)]
|
||||
struct AudioMetadata {
|
||||
sample_rate: u32,
|
||||
channels: u16,
|
||||
bit_depth: Option<u32>,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn extract_audio_metadata(data: &[u8]) -> Result<(u32, u16), String> {
|
||||
let meta = extract_audio_metadata_full(data)?;
|
||||
Ok((meta.sample_rate, meta.channels))
|
||||
@@ -642,6 +645,7 @@ pub struct Player {
|
||||
/// Audio settings (exclusive mode, DAC passthrough, etc.)
|
||||
audio_settings: Arc<Mutex<AudioSettings>>,
|
||||
/// Visualizer tap for audio sample capture (optional)
|
||||
#[allow(dead_code)]
|
||||
visualizer_tap: Option<VisualizerTap>,
|
||||
}
|
||||
|
||||
@@ -790,7 +794,9 @@ impl Player {
|
||||
let mut current_sample_rate: Option<u32> = None;
|
||||
let mut current_channels: Option<u16> = None;
|
||||
|
||||
#[allow(dead_code)]
|
||||
const MAX_INIT_RETRIES: u32 = 5;
|
||||
#[allow(dead_code)]
|
||||
const RETRY_DELAY_MS: u64 = 500;
|
||||
|
||||
let mut current_engine: Option<PlaybackEngine> = None;
|
||||
@@ -808,7 +814,7 @@ impl Player {
|
||||
|
||||
log::info!("Audio thread ready and waiting for commands");
|
||||
|
||||
let mut handle_command = |command: AudioCommand,
|
||||
let handle_command = |command: AudioCommand,
|
||||
current_engine: &mut Option<PlaybackEngine>,
|
||||
current_audio_data: &mut Option<Vec<u8>>,
|
||||
current_streaming_source: &mut Option<Arc<BufferedMediaSource>>,
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//! This abstraction allows the player to work with both approaches transparently.
|
||||
|
||||
use crate::audio::AlsaDirectStream;
|
||||
use rodio::{OutputStream, OutputStreamHandle, Sink, Source};
|
||||
use rodio::{OutputStreamHandle, Sink, Source};
|
||||
use std::sync::atomic::{AtomicBool, AtomicU64, Ordering};
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
@@ -270,6 +270,7 @@ impl PlaybackEngine {
|
||||
}
|
||||
|
||||
/// Get current position in seconds (for ALSA Direct only)
|
||||
#[allow(dead_code)]
|
||||
pub fn position_secs(&self) -> Option<u64> {
|
||||
match self {
|
||||
Self::Rodio { .. } => None, // Rodio doesn't expose position directly
|
||||
@@ -286,6 +287,7 @@ impl PlaybackEngine {
|
||||
}
|
||||
|
||||
/// Get duration in seconds (for ALSA Direct only)
|
||||
#[allow(dead_code)]
|
||||
pub fn duration_secs(&self) -> Option<u64> {
|
||||
match self {
|
||||
Self::Rodio { .. } => None,
|
||||
@@ -302,6 +304,7 @@ impl PlaybackEngine {
|
||||
}
|
||||
|
||||
/// Check if using ALSA Direct engine
|
||||
#[allow(dead_code)]
|
||||
pub fn is_alsa_direct(&self) -> bool {
|
||||
matches!(self, Self::AlsaDirect { .. })
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ use serde_json::Value;
|
||||
|
||||
use crate::playlist_import::errors::PlaylistImportError;
|
||||
use crate::playlist_import::models::{ImportPlaylist, ImportProvider, ImportTrack};
|
||||
use crate::playlist_import::providers::ProviderCredentials;
|
||||
|
||||
// Cloudflare Workers proxy URL - handles credentials
|
||||
const SPOTIFY_PROXY_URL: &str = "https://qbz-api-proxy.blitzkriegfc.workers.dev/spotify";
|
||||
|
||||
@@ -8,7 +8,6 @@ use tokio::time::sleep;
|
||||
|
||||
use crate::playlist_import::errors::PlaylistImportError;
|
||||
use crate::playlist_import::models::{ImportPlaylist, ImportProvider, ImportTrack};
|
||||
use crate::playlist_import::providers::ProviderCredentials;
|
||||
|
||||
const RATE_LIMIT_DELAY_MS: u64 = 200; // Delay between API calls to avoid 429
|
||||
|
||||
|
||||
@@ -444,7 +444,7 @@ pub async fn get_playlist_suggestions(
|
||||
// Find tracks by this artist in our candidates and boost them
|
||||
// Note: We don't have track->artist mapping here, so this is implicit
|
||||
// through the scoring system (tracks played when artist was played)
|
||||
for (track_id, score) in candidates.iter_mut() {
|
||||
for (_track_id, score) in candidates.iter_mut() {
|
||||
// Boost slightly based on artist affinity (implicit)
|
||||
*score += artist_score * 0.1;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user