1
0
Fork 0
mirror of https://github.com/librespot-org/librespot.git synced 2025-10-03 01:39:28 +02:00

style: format with style edition 2024

This commit is contained in:
Roderick van Domburg 2025-08-13 23:09:59 +02:00
parent 056d125cb2
commit 218eced556
No known key found for this signature in database
GPG key ID: 607FA06CB5236AE0
62 changed files with 196 additions and 139 deletions

View file

@ -5,21 +5,21 @@ use std::{
fs, fs,
io::{self, Read, Seek, SeekFrom}, io::{self, Read, Seek, SeekFrom},
sync::{ sync::{
atomic::{AtomicBool, AtomicUsize, Ordering},
Arc, OnceLock, Arc, OnceLock,
atomic::{AtomicBool, AtomicUsize, Ordering},
}, },
time::Duration, time::Duration,
}; };
use futures_util::{future::IntoStream, StreamExt, TryFutureExt}; use futures_util::{StreamExt, TryFutureExt, future::IntoStream};
use hyper::{body::Incoming, header::CONTENT_RANGE, Response, StatusCode}; use hyper::{Response, StatusCode, body::Incoming, header::CONTENT_RANGE};
use hyper_util::client::legacy::ResponseFuture; use hyper_util::client::legacy::ResponseFuture;
use parking_lot::{Condvar, Mutex}; use parking_lot::{Condvar, Mutex};
use tempfile::NamedTempFile; use tempfile::NamedTempFile;
use thiserror::Error; use thiserror::Error;
use tokio::sync::{mpsc, oneshot, Semaphore}; use tokio::sync::{Semaphore, mpsc, oneshot};
use librespot_core::{cdn_url::CdnUrl, Error, FileId, Session}; use librespot_core::{Error, FileId, Session, cdn_url::CdnUrl};
use self::receive::audio_file_fetch; use self::receive::audio_file_fetch;

View file

@ -12,7 +12,7 @@ use hyper::StatusCode;
use tempfile::NamedTempFile; use tempfile::NamedTempFile;
use tokio::sync::{mpsc, oneshot}; use tokio::sync::{mpsc, oneshot};
use librespot_core::{http_client::HttpClient, session::Session, Error}; use librespot_core::{Error, http_client::HttpClient, session::Session};
use crate::range_set::{Range, RangeSet}; use crate::range_set::{Range, RangeSet};

View file

@ -4,7 +4,7 @@ use crate::{
autoplay_context_request::AutoplayContextRequest, context::Context, autoplay_context_request::AutoplayContextRequest, context::Context,
transfer_state::TransferState, transfer_state::TransferState,
}, },
state::{context::ContextType, ConnectState}, state::{ConnectState, context::ContextType},
}; };
use std::{ use std::{
cmp::PartialEq, cmp::PartialEq,

View file

@ -1,4 +1,4 @@
use rand::{rngs::SmallRng, Rng, SeedableRng}; use rand::{Rng, SeedableRng, rngs::SmallRng};
use std::{ use std::{
ops::{Deref, DerefMut}, ops::{Deref, DerefMut},
vec::IntoIter, vec::IntoIter,

View file

@ -1,13 +1,14 @@
use crate::{ use crate::{
LoadContextOptions, LoadRequestOptions, PlayContext,
context_resolver::{ContextAction, ContextResolver, ResolveContext}, context_resolver::{ContextAction, ContextResolver, ResolveContext},
core::{ core::{
Error, Session, SpotifyId,
authentication::Credentials, authentication::Credentials,
dealer::{ dealer::{
manager::{BoxedStream, BoxedStreamResult, Reply, RequestReply}, manager::{BoxedStream, BoxedStreamResult, Reply, RequestReply},
protocol::{Command, FallbackWrapper, Message, Request}, protocol::{Command, FallbackWrapper, Message, Request},
}, },
session::UserAttributes, session::UserAttributes,
Error, Session, SpotifyId,
}, },
model::{LoadRequest, PlayingTrack, SpircPlayStatus}, model::{LoadRequest, PlayingTrack, SpircPlayStatus},
playback::{ playback::{
@ -28,15 +29,14 @@ use crate::{
provider::IsProvider, provider::IsProvider,
{ConnectConfig, ConnectState}, {ConnectConfig, ConnectState},
}, },
LoadContextOptions, LoadRequestOptions, PlayContext,
}; };
use futures_util::StreamExt; use futures_util::StreamExt;
use librespot_protocol::context_page::ContextPage; use librespot_protocol::context_page::ContextPage;
use protobuf::MessageField; use protobuf::MessageField;
use std::{ use std::{
future::Future, future::Future,
sync::atomic::{AtomicUsize, Ordering},
sync::Arc, sync::Arc,
sync::atomic::{AtomicUsize, Ordering},
time::{Duration, SystemTime, UNIX_EPOCH}, time::{Duration, SystemTime, UNIX_EPOCH},
}; };
use thiserror::Error; use thiserror::Error;
@ -951,7 +951,8 @@ impl SpircTask {
{ {
debug!( debug!(
"ignoring context update for <{:?}>, because it isn't the current context <{}>", "ignoring context update for <{:?}>, because it isn't the current context <{}>",
update_context.context.uri, self.connect_state.context_uri() update_context.context.uri,
self.connect_state.context_uri()
) )
} else { } else {
self.context_resolver.add(ResolveContext::from_context( self.context_resolver.add(ResolveContext::from_context(
@ -1615,7 +1616,9 @@ impl SpircTask {
let uri = String::from_utf8(uri)?; let uri = String::from_utf8(uri)?;
if self.connect_state.context_uri() != &uri { if self.connect_state.context_uri() != &uri {
debug!("ignoring playlist modification update for playlist <{uri}>, because it isn't the current context"); debug!(
"ignoring playlist modification update for playlist <{uri}>, because it isn't the current context"
);
return Ok(()); return Ok(());
} }

View file

@ -9,8 +9,8 @@ mod transfer;
use crate::{ use crate::{
core::{ core::{
config::DeviceType, date::Date, dealer::protocol::Request, spclient::SpClientResult, Error, Session, config::DeviceType, date::Date, dealer::protocol::Request,
version, Error, Session, spclient::SpClientResult, version,
}, },
model::SpircPlayStatus, model::SpircPlayStatus,
protocol::{ protocol::{

View file

@ -9,9 +9,9 @@ use crate::{
}, },
shuffle_vec::ShuffleVec, shuffle_vec::ShuffleVec,
state::{ state::{
ConnectState, SPOTIFY_MAX_NEXT_TRACKS_SIZE, StateError,
metadata::Metadata, metadata::Metadata,
provider::{IsProvider, Provider}, provider::{IsProvider, Provider},
ConnectState, StateError, SPOTIFY_MAX_NEXT_TRACKS_SIZE,
}, },
}; };
use protobuf::MessageField; use protobuf::MessageField;

View file

@ -1,9 +1,9 @@
use crate::{ use crate::{
core::{dealer::protocol::SetQueueCommand, Error}, core::{Error, dealer::protocol::SetQueueCommand},
state::{ state::{
ConnectState,
context::{ContextType, ResetContext}, context::{ContextType, ResetContext},
metadata::Metadata, metadata::Metadata,
ConnectState,
}, },
}; };
use protobuf::MessageField; use protobuf::MessageField;

View file

@ -2,9 +2,9 @@ use crate::{
core::Error, core::Error,
protocol::player::ContextPlayerOptions, protocol::player::ContextPlayerOptions,
state::{ state::{
ConnectState, StateError,
context::{ContextType, ResetContext}, context::{ContextType, ResetContext},
metadata::Metadata, metadata::Metadata,
ConnectState, StateError,
}, },
}; };
use protobuf::MessageField; use protobuf::MessageField;

View file

@ -1,5 +1,5 @@
use crate::state::provider::IsProvider;
use crate::state::ConnectState; use crate::state::ConnectState;
use crate::state::provider::IsProvider;
use librespot_protocol::player::Restrictions; use librespot_protocol::player::Restrictions;
use protobuf::MessageField; use protobuf::MessageField;

View file

@ -2,10 +2,10 @@ use crate::{
core::{Error, SpotifyId}, core::{Error, SpotifyId},
protocol::player::ProvidedTrack, protocol::player::ProvidedTrack,
state::{ state::{
ConnectState, SPOTIFY_MAX_NEXT_TRACKS_SIZE, SPOTIFY_MAX_PREV_TRACKS_SIZE, StateError,
context::ContextType, context::ContextType,
metadata::Metadata, metadata::Metadata,
provider::{IsProvider, Provider}, provider::{IsProvider, Provider},
ConnectState, StateError, SPOTIFY_MAX_NEXT_TRACKS_SIZE, SPOTIFY_MAX_PREV_TRACKS_SIZE,
}, },
}; };
use protobuf::MessageField; use protobuf::MessageField;

View file

@ -139,7 +139,7 @@ impl ApResolver {
_ => { _ => {
return Err(Error::unimplemented(format!( return Err(Error::unimplemented(format!(
"No implementation to resolve access point {endpoint}" "No implementation to resolve access point {endpoint}"
))) )));
} }
}; };

View file

@ -5,7 +5,7 @@ use bytes::Bytes;
use thiserror::Error; use thiserror::Error;
use tokio::sync::oneshot; use tokio::sync::oneshot;
use crate::{packet::PacketType, util::SeqGenerator, Error, FileId, SpotifyId}; use crate::{Error, FileId, SpotifyId, packet::PacketType, util::SeqGenerator};
#[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)] #[derive(Debug, Hash, PartialEq, Eq, Copy, Clone)]
pub struct AudioKey(pub [u8; 16]); pub struct AudioKey(pub [u8; 16]);

View file

@ -1,8 +1,8 @@
use std::io::{self, Read}; use std::io::{self, Read};
use aes::Aes192; use aes::Aes192;
use base64::engine::general_purpose::STANDARD as BASE64;
use base64::engine::Engine as _; use base64::engine::Engine as _;
use base64::engine::general_purpose::STANDARD as BASE64;
use byteorder::{BigEndian, ByteOrder}; use byteorder::{BigEndian, ByteOrder};
use pbkdf2::pbkdf2_hmac; use pbkdf2::pbkdf2_hmac;
use protobuf::Enum; use protobuf::Enum;
@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
use sha1::{Digest, Sha1}; use sha1::{Digest, Sha1};
use thiserror::Error; use thiserror::Error;
use crate::{protocol::authentication::AuthenticationType, Error}; use crate::{Error, protocol::authentication::AuthenticationType};
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum AuthenticationError { pub enum AuthenticationError {

View file

@ -12,7 +12,7 @@ use parking_lot::Mutex;
use priority_queue::PriorityQueue; use priority_queue::PriorityQueue;
use thiserror::Error; use thiserror::Error;
use crate::{authentication::Credentials, error::ErrorKind, Error, FileId}; use crate::{Error, FileId, authentication::Credentials, error::ErrorKind};
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum CacheError { pub enum CacheError {

View file

@ -5,11 +5,11 @@ use thiserror::Error;
use time::Duration; use time::Duration;
use url::Url; use url::Url;
use super::{date::Date, Error, FileId, Session}; use super::{Error, FileId, Session, date::Date};
use librespot_protocol as protocol; use librespot_protocol as protocol;
use protocol::storage_resolve::storage_resolve_response::Result as StorageResolveResponse_Result;
use protocol::storage_resolve::StorageResolveResponse as CdnUrlMessage; use protocol::storage_resolve::StorageResolveResponse as CdnUrlMessage;
use protocol::storage_resolve::storage_resolve_response::Result as StorageResolveResponse_Result;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MaybeExpiringUrl(pub String, pub Option<Date>); pub struct MaybeExpiringUrl(pub String, pub Option<Date>);
@ -201,7 +201,9 @@ impl TryFrom<CdnUrlMessage> for MaybeExpiringUrls {
expiry = Some(Date::from(with_margin)); expiry = Some(Date::from(with_margin));
} }
} else { } else {
warn!("Cannot parse CDN URL expiry timestamp '{exp_str}' from '{cdn_url}'"); warn!(
"Cannot parse CDN URL expiry timestamp '{exp_str}' from '{cdn_url}'"
);
} }
} else { } else {
warn!("Unknown CDN URL format: {cdn_url}"); warn!("Unknown CDN URL format: {cdn_url}");
@ -225,10 +227,18 @@ mod test {
let mut msg = CdnUrlMessage::new(); let mut msg = CdnUrlMessage::new();
msg.result = StorageResolveResponse_Result::CDN.into(); msg.result = StorageResolveResponse_Result::CDN.into();
msg.cdnurl = vec![ msg.cdnurl = vec![
format!("https://audio-cf.spotifycdn.com/audio/844ecdb297a87ebfee4399f28892ef85d9ba725f?verify={timestamp}-4R3I2w2q7OfNkR%2FGH8qH7xtIKUPlDxywBuADY%2BsvMeU%3D"), format!(
format!("https://audio-ak-spotify-com.akamaized.net/audio/foo?__token__=exp={timestamp}~hmac=4e661527574fab5793adb99cf04e1c2ce12294c71fe1d39ffbfabdcfe8ce3b41"), "https://audio-cf.spotifycdn.com/audio/844ecdb297a87ebfee4399f28892ef85d9ba725f?verify={timestamp}-4R3I2w2q7OfNkR%2FGH8qH7xtIKUPlDxywBuADY%2BsvMeU%3D"
format!("https://audio-gm-off.spotifycdn.com/audio/foo?Expires={timestamp}~FullPath~hmac=IIZA28qptl8cuGLq15-SjHKHtLoxzpy_6r_JpAU4MfM="), ),
format!("https://audio4-fa.scdn.co/audio/foo?{timestamp}_0GKSyXjLaTW1BksFOyI4J7Tf9tZDbBUNNPu9Mt4mhH4="), format!(
"https://audio-ak-spotify-com.akamaized.net/audio/foo?__token__=exp={timestamp}~hmac=4e661527574fab5793adb99cf04e1c2ce12294c71fe1d39ffbfabdcfe8ce3b41"
),
format!(
"https://audio-gm-off.spotifycdn.com/audio/foo?Expires={timestamp}~FullPath~hmac=IIZA28qptl8cuGLq15-SjHKHtLoxzpy_6r_JpAU4MfM="
),
format!(
"https://audio4-fa.scdn.co/audio/foo?{timestamp}_0GKSyXjLaTW1BksFOyI4J7Tf9tZDbBUNNPu9Mt4mhH4="
),
"https://audio4-fa.scdn.co/foo?baz".to_string(), "https://audio4-fa.scdn.co/foo?baz".to_string(),
]; ];
msg.fileid = vec![0]; msg.fileid = vec![0];

View file

@ -9,12 +9,12 @@ use std::{
use byteorder::{BigEndian, ByteOrder}; use byteorder::{BigEndian, ByteOrder};
use bytes::Bytes; use bytes::Bytes;
use futures_core::Stream; use futures_core::Stream;
use futures_util::{lock::BiLock, ready, StreamExt}; use futures_util::{StreamExt, lock::BiLock, ready};
use num_traits::FromPrimitive; use num_traits::FromPrimitive;
use thiserror::Error; use thiserror::Error;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use crate::{packet::PacketType, util::SeqGenerator, Error}; use crate::{Error, packet::PacketType, util::SeqGenerator};
component! { component! {
ChannelManager : ChannelManagerInner { ChannelManager : ChannelManagerInner {

View file

@ -13,7 +13,7 @@ use tokio::net::TcpStream;
use tokio_util::codec::Framed; use tokio_util::codec::Framed;
use url::Url; use url::Url;
use crate::{authentication::Credentials, packet::PacketType, version, Error}; use crate::{Error, authentication::Credentials, packet::PacketType, version};
use crate::protocol::keyexchange::{APLoginFailed, ErrorCode}; use crate::protocol::keyexchange::{APLoginFailed, ErrorCode};

View file

@ -1,8 +1,8 @@
use std::{fmt::Debug, ops::Deref}; use std::{fmt::Debug, ops::Deref};
use time::{ use time::{
error::ComponentRange, format_description::well_known::Iso8601, Date as _Date, OffsetDateTime, Date as _Date, OffsetDateTime, PrimitiveDateTime, Time, error::ComponentRange,
PrimitiveDateTime, Time, format_description::well_known::Iso8601,
}; };
use crate::Error; use crate::Error;

View file

@ -7,8 +7,8 @@ use tokio_stream::wrappers::UnboundedReceiverStream;
use url::Url; use url::Url;
use super::{ use super::{
protocol::Message, Builder, Dealer, GetUrlResult, Request, RequestHandler, Responder, Response, Builder, Dealer, GetUrlResult, Request, RequestHandler, Responder, Response, Subscription,
Subscription, protocol::Message,
}; };
use crate::{Error, Session}; use crate::{Error, Session};

View file

@ -6,22 +6,22 @@ use std::{
iter, iter,
pin::Pin, pin::Pin,
sync::{ sync::{
atomic::{self, AtomicBool},
Arc, Arc,
atomic::{self, AtomicBool},
}, },
task::Poll, task::Poll,
time::Duration, time::Duration,
}; };
use futures_core::{Future, Stream}; use futures_core::{Future, Stream};
use futures_util::{future::join_all, SinkExt, StreamExt}; use futures_util::{SinkExt, StreamExt, future::join_all};
use parking_lot::Mutex; use parking_lot::Mutex;
use thiserror::Error; use thiserror::Error;
use tokio::{ use tokio::{
select, select,
sync::{ sync::{
mpsc::{self, UnboundedReceiver},
Semaphore, Semaphore,
mpsc::{self, UnboundedReceiver},
}, },
task::JoinHandle, task::JoinHandle,
}; };
@ -35,9 +35,8 @@ use self::{
}; };
use crate::{ use crate::{
socket, Error, socket,
util::{keep_flushing, CancelOnDrop, TimeoutOnDrop}, util::{CancelOnDrop, TimeoutOnDrop, keep_flushing},
Error,
}; };
type WsMessage = tungstenite::Message; type WsMessage = tungstenite::Message;

View file

@ -5,8 +5,8 @@ pub use request::*;
use std::collections::HashMap; use std::collections::HashMap;
use std::io::{Error as IoError, Read}; use std::io::{Error as IoError, Read};
use crate::{deserialize_with::json_proto, Error}; use crate::{Error, deserialize_with::json_proto};
use base64::{prelude::BASE64_STANDARD, DecodeError, Engine}; use base64::{DecodeError, Engine, prelude::BASE64_STANDARD};
use flate2::read::GzDecoder; use flate2::read::GzDecoder;
use log::LevelFilter; use log::LevelFilter;
use serde::Deserialize; use serde::Deserialize;

View file

@ -1,5 +1,5 @@
use base64::prelude::BASE64_STANDARD;
use base64::Engine; use base64::Engine;
use base64::prelude::BASE64_STANDARD;
use protobuf::MessageFull; use protobuf::MessageFull;
use serde::de::{Error, Unexpected}; use serde::de::{Error, Unexpected};
use serde::{Deserialize, Deserializer}; use serde::{Deserialize, Deserializer};

View file

@ -15,7 +15,7 @@ use http::{
use protobuf::Error as ProtobufError; use protobuf::Error as ProtobufError;
use thiserror::Error; use thiserror::Error;
use tokio::sync::{ use tokio::sync::{
mpsc::error::SendError, oneshot::error::RecvError, AcquireError, TryAcquireError, AcquireError, TryAcquireError, mpsc::error::SendError, oneshot::error::RecvError,
}; };
use url::ParseError; use url::ParseError;

View file

@ -2,7 +2,7 @@ use std::fmt;
use librespot_protocol as protocol; use librespot_protocol as protocol;
use crate::{spotify_id::to_base16, Error}; use crate::{Error, spotify_id::to_base16};
const RAW_LEN: usize = 20; const RAW_LEN: usize = 20;

View file

@ -5,17 +5,17 @@ use std::{
}; };
use bytes::Bytes; use bytes::Bytes;
use futures_util::{future::IntoStream, FutureExt}; use futures_util::{FutureExt, future::IntoStream};
use governor::{ use governor::{
clock::MonotonicClock, middleware::NoOpMiddleware, state::InMemoryState, Quota, RateLimiter, Quota, RateLimiter, clock::MonotonicClock, middleware::NoOpMiddleware, state::InMemoryState,
}; };
use http::{header::HeaderValue, Uri}; use http::{Uri, header::HeaderValue};
use http_body_util::{BodyExt, Full}; use http_body_util::{BodyExt, Full};
use hyper::{body::Incoming, header::USER_AGENT, HeaderMap, Request, Response, StatusCode}; use hyper::{HeaderMap, Request, Response, StatusCode, body::Incoming, header::USER_AGENT};
use hyper_proxy2::{Intercept, Proxy, ProxyConnector}; use hyper_proxy2::{Intercept, Proxy, ProxyConnector};
use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder}; use hyper_rustls::{HttpsConnector, HttpsConnectorBuilder};
use hyper_util::{ use hyper_util::{
client::legacy::{connect::HttpConnector, Client, ResponseFuture}, client::legacy::{Client, ResponseFuture, connect::HttpConnector},
rt::TokioExecutor, rt::TokioExecutor,
}; };
use nonzero_ext::nonzero; use nonzero_ext::nonzero;
@ -24,10 +24,10 @@ use thiserror::Error;
use url::Url; use url::Url;
use crate::{ use crate::{
config::{os_version, OS},
date::Date,
version::{spotify_version, FALLBACK_USER_AGENT, VERSION_STRING},
Error, Error,
config::{OS, os_version},
date::Date,
version::{FALLBACK_USER_AGENT, VERSION_STRING, spotify_version},
}; };
// The 30 seconds interval is documented by Spotify, but the calls per interval // The 30 seconds interval is documented by Spotify, but the calls per interval

View file

@ -1,17 +1,17 @@
use crate::config::OS; use crate::config::OS;
use crate::spclient::CLIENT_TOKEN; use crate::spclient::CLIENT_TOKEN;
use crate::token::Token; use crate::token::Token;
use crate::{util, Error, SessionConfig}; use crate::{Error, SessionConfig, util};
use bytes::Bytes; use bytes::Bytes;
use http::{header::ACCEPT, HeaderValue, Method, Request}; use http::{HeaderValue, Method, Request, header::ACCEPT};
use librespot_protocol::login5::login_response::Response; use librespot_protocol::login5::login_response::Response;
use librespot_protocol::{ use librespot_protocol::{
client_info::ClientInfo, client_info::ClientInfo,
credentials::{Password, StoredCredential}, credentials::{Password, StoredCredential},
hashcash::HashcashSolution, hashcash::HashcashSolution,
login5::{ login5::{
login_request::Login_method, ChallengeSolution, LoginError, LoginOk, LoginRequest, ChallengeSolution, LoginError, LoginOk, LoginRequest, LoginResponse,
LoginResponse, login_request::Login_method,
}, },
}; };
use protobuf::well_known_types::duration::Duration as ProtoDuration; use protobuf::well_known_types::duration::Duration as ProtoDuration;

View file

@ -11,7 +11,7 @@ use futures_util::FutureExt;
use protobuf::Message; use protobuf::Message;
use tokio::sync::{mpsc, oneshot}; use tokio::sync::{mpsc, oneshot};
use crate::{packet::PacketType, protocol, util::SeqGenerator, Error}; use crate::{Error, packet::PacketType, protocol, util::SeqGenerator};
mod types; mod types;
pub use self::types::*; pub use self::types::*;

View file

@ -4,7 +4,7 @@ use byteorder::{BigEndian, WriteBytesExt};
use protobuf::Message; use protobuf::Message;
use thiserror::Error; use thiserror::Error;
use crate::{packet::PacketType, protocol, Error}; use crate::{Error, packet::PacketType, protocol};
#[derive(Debug, PartialEq, Eq)] #[derive(Debug, PartialEq, Eq)]
pub enum MercuryMethod { pub enum MercuryMethod {

View file

@ -12,6 +12,7 @@ use std::{
use crate::dealer::manager::DealerManager; use crate::dealer::manager::DealerManager;
use crate::{ use crate::{
Error,
apresolve::{ApResolver, SocketAddress}, apresolve::{ApResolver, SocketAddress},
audio_key::AudioKeyManager, audio_key::AudioKeyManager,
authentication::Credentials, authentication::Credentials,
@ -26,7 +27,6 @@ use crate::{
protocol::keyexchange::ErrorCode, protocol::keyexchange::ErrorCode,
spclient::SpClient, spclient::SpClient,
token::TokenProvider, token::TokenProvider,
Error,
}; };
use byteorder::{BigEndian, ByteOrder}; use byteorder::{BigEndian, ByteOrder};
use bytes::Bytes; use bytes::Bytes;
@ -40,7 +40,7 @@ use quick_xml::events::Event;
use thiserror::Error; use thiserror::Error;
use tokio::{ use tokio::{
sync::mpsc, sync::mpsc,
time::{sleep, Duration as TokioDuration, Instant as TokioInstant, Sleep}, time::{Duration as TokioDuration, Instant as TokioInstant, Sleep, sleep},
}; };
use tokio_stream::wrappers::UnboundedReceiverStream; use tokio_stream::wrappers::UnboundedReceiverStream;
use uuid::Uuid; use uuid::Uuid;

View file

@ -3,8 +3,9 @@ use std::{
time::{Duration, Instant}, time::{Duration, Instant},
}; };
use crate::config::{os_version, OS}; use crate::config::{OS, os_version};
use crate::{ use crate::{
Error, FileId, SpotifyId,
apresolve::SocketAddress, apresolve::SocketAddress,
config::SessionConfig, config::SessionConfig,
error::ErrorKind, error::ErrorKind,
@ -21,15 +22,14 @@ use crate::{
token::Token, token::Token,
util, util,
version::spotify_semantic_version, version::spotify_semantic_version,
Error, FileId, SpotifyId,
}; };
use bytes::Bytes; use bytes::Bytes;
use data_encoding::HEXUPPER_PERMISSIVE; use data_encoding::HEXUPPER_PERMISSIVE;
use futures_util::future::IntoStream; use futures_util::future::IntoStream;
use http::{header::HeaderValue, Uri}; use http::{Uri, header::HeaderValue};
use hyper::{ use hyper::{
header::{HeaderName, ACCEPT, AUTHORIZATION, CONTENT_TYPE, RANGE},
HeaderMap, Method, Request, HeaderMap, Method, Request,
header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE, HeaderName, RANGE},
}; };
use hyper_util::client::legacy::ResponseFuture; use hyper_util::client::legacy::ResponseFuture;
use protobuf::{Enum, Message, MessageFull}; use protobuf::{Enum, Message, MessageFull};
@ -335,7 +335,7 @@ impl SpClient {
Some(unknown) => { Some(unknown) => {
return Err(Error::unimplemented(format!( return Err(Error::unimplemented(format!(
"Unknown client token response type: {unknown:?}" "Unknown client token response type: {unknown:?}"
))) )));
} }
None => return Err(Error::failed_precondition("No client token response type")), None => return Err(Error::failed_precondition("No client token response type")),
} }
@ -892,7 +892,9 @@ impl SpClient {
pub async fn get_rootlist(&self, from: usize, length: Option<usize>) -> SpClientResult { pub async fn get_rootlist(&self, from: usize, length: Option<usize>) -> SpClientResult {
let length = length.unwrap_or(120); let length = length.unwrap_or(120);
let user = self.session().username(); let user = self.session().username();
let endpoint = format!("/playlist/v2/user/{user}/rootlist?decorate=revision,attributes,length,owner,capabilities,status_code&from={from}&length={length}"); let endpoint = format!(
"/playlist/v2/user/{user}/rootlist?decorate=revision,attributes,length,owner,capabilities,status_code&from={from}&length={length}"
);
self.request(&Method::GET, &endpoint, None, None).await self.request(&Method::GET, &endpoint, None, None).await
} }

View file

@ -1,7 +1,7 @@
use crate::Error; use crate::Error;
use byteorder::{BigEndian, ByteOrder}; use byteorder::{BigEndian, ByteOrder};
use futures_core::ready; use futures_core::ready;
use futures_util::{future, FutureExt, Sink, SinkExt}; use futures_util::{FutureExt, Sink, SinkExt, future};
use hmac::digest::Digest; use hmac::digest::Digest;
use sha1::Sha1; use sha1::Sha1;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
@ -62,11 +62,12 @@ impl<T: Send + 'static> Future for TimeoutOnDrop<T> {
type Output = <JoinHandle<T> as Future>::Output; type Output = <JoinHandle<T> as Future>::Output;
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> { fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let r = ready!(self let r = ready!(
.handle self.handle
.as_mut() .as_mut()
.expect("Polled after ready") .expect("Polled after ready")
.poll_unpin(cx)); .poll_unpin(cx)
);
self.handle = None; self.handle = None;
Poll::Ready(r) Poll::Ready(r)
} }

View file

@ -211,7 +211,9 @@ async fn avahi_task(
break 'wait_avahi; break 'wait_avahi;
} }
} }
log::warn!("Failed to connect to Avahi, zeroconf discovery will not work until avahi-daemon is started. Check that it is installed and running"); log::warn!(
"Failed to connect to Avahi, zeroconf discovery will not work until avahi-daemon is started. Check that it is installed and running"
);
// If it didn't, wait for the signal // If it didn't, wait for the signal
match stream.next().await { match stream.next().await {

View file

@ -6,13 +6,13 @@ use std::{
}; };
use aes::cipher::{KeyIvInit, StreamCipher}; use aes::cipher::{KeyIvInit, StreamCipher};
use base64::engine::general_purpose::STANDARD as BASE64;
use base64::engine::Engine as _; use base64::engine::Engine as _;
use base64::engine::general_purpose::STANDARD as BASE64;
use bytes::Bytes; use bytes::Bytes;
use futures_util::{FutureExt, TryFutureExt}; use futures_util::{FutureExt, TryFutureExt};
use hmac::{Hmac, Mac}; use hmac::{Hmac, Mac};
use http_body_util::{BodyExt, Full}; use http_body_util::{BodyExt, Full};
use hyper::{body::Incoming, Method, Request, Response, StatusCode}; use hyper::{Method, Request, Response, StatusCode, body::Incoming};
use hyper_util::{rt::TokioIo, server::graceful::GracefulShutdown}; use hyper_util::{rt::TokioIo, server::graceful::GracefulShutdown};
use log::{debug, error, warn}; use log::{debug, error, warn};
@ -24,7 +24,7 @@ use super::{DiscoveryError, DiscoveryEvent};
use crate::{ use crate::{
core::config::DeviceType, core::config::DeviceType,
core::{authentication::Credentials, diffie_hellman::DhLocalKeys, Error}, core::{Error, authentication::Credentials, diffie_hellman::DhLocalKeys},
}; };
type Aes128Ctr = ctr::Ctr128BE<aes::Aes128>; type Aes128Ctr = ctr::Ctr128BE<aes::Aes128>;

View file

@ -4,6 +4,7 @@ use std::{
}; };
use crate::{ use crate::{
Metadata,
artist::Artists, artist::Artists,
availability::Availabilities, availability::Availabilities,
copyright::Copyrights, copyright::Copyrights,
@ -14,14 +15,13 @@ use crate::{
sale_period::SalePeriods, sale_period::SalePeriods,
track::Tracks, track::Tracks,
util::{impl_deref_wrapped, impl_try_from_repeated}, util::{impl_deref_wrapped, impl_try_from_repeated},
Metadata,
}; };
use librespot_core::{date::Date, Error, Session, SpotifyId}; use librespot_core::{Error, Session, SpotifyId, date::Date};
use librespot_protocol as protocol; use librespot_protocol as protocol;
pub use protocol::metadata::album::Type as AlbumType;
use protocol::metadata::Disc as DiscMessage; use protocol::metadata::Disc as DiscMessage;
pub use protocol::metadata::album::Type as AlbumType;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Album { pub struct Album {

View file

@ -4,6 +4,7 @@ use std::{
}; };
use crate::{ use crate::{
Metadata,
album::Albums, album::Albums,
availability::Availabilities, availability::Availabilities,
external_id::ExternalIds, external_id::ExternalIds,
@ -13,7 +14,6 @@ use crate::{
sale_period::SalePeriods, sale_period::SalePeriods,
track::Tracks, track::Tracks,
util::{impl_deref_wrapped, impl_from_repeated, impl_try_from_repeated}, util::{impl_deref_wrapped, impl_from_repeated, impl_try_from_repeated},
Metadata,
}; };
use librespot_core::{Error, Session, SpotifyId}; use librespot_core::{Error, Session, SpotifyId};
@ -294,7 +294,7 @@ impl TryFrom<&ActivityPeriodMessage> for ActivityPeriod {
_ => { _ => {
return Err(librespot_core::Error::failed_precondition( return Err(librespot_core::Error::failed_precondition(
"ActivityPeriod is expected to be either a decade or timespan", "ActivityPeriod is expected to be either a decade or timespan",
)) ));
} }
}; };
Ok(activity_period) Ok(activity_period)

View file

@ -1,6 +1,7 @@
use std::fmt::Debug; use std::fmt::Debug;
use crate::{ use crate::{
Metadata,
artist::ArtistsWithRole, artist::ArtistsWithRole,
availability::{AudioItemAvailability, Availabilities, UnavailabilityReason}, availability::{AudioItemAvailability, Availabilities, UnavailabilityReason},
episode::Episode, episode::Episode,
@ -8,13 +9,12 @@ use crate::{
image::{ImageSize, Images}, image::{ImageSize, Images},
restriction::Restrictions, restriction::Restrictions,
track::{Track, Tracks}, track::{Track, Tracks},
Metadata,
}; };
use super::file::AudioFiles; use super::file::AudioFiles;
use librespot_core::{ use librespot_core::{
date::Date, session::UserData, spotify_id::SpotifyItemType, Error, Session, SpotifyId, Error, Session, SpotifyId, date::Date, session::UserData, spotify_id::SpotifyItemType,
}; };
pub type AudioItemResult = Result<AudioItem, Error>; pub type AudioItemResult = Result<AudioItem, Error>;

View file

@ -6,8 +6,8 @@ use std::{
use crate::util::{impl_deref_wrapped, impl_from_repeated}; use crate::util::{impl_deref_wrapped, impl_from_repeated};
use librespot_protocol as protocol; use librespot_protocol as protocol;
pub use protocol::metadata::copyright::Type as CopyrightType;
use protocol::metadata::Copyright as CopyrightMessage; use protocol::metadata::Copyright as CopyrightMessage;
pub use protocol::metadata::copyright::Type as CopyrightType;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Copyright { pub struct Copyright {

View file

@ -4,6 +4,7 @@ use std::{
}; };
use crate::{ use crate::{
Metadata,
audio::file::AudioFiles, audio::file::AudioFiles,
availability::Availabilities, availability::Availabilities,
content_rating::ContentRatings, content_rating::ContentRatings,
@ -12,10 +13,9 @@ use crate::{
restriction::Restrictions, restriction::Restrictions,
util::{impl_deref_wrapped, impl_try_from_repeated}, util::{impl_deref_wrapped, impl_try_from_repeated},
video::VideoFiles, video::VideoFiles,
Metadata,
}; };
use librespot_core::{date::Date, Error, Session, SpotifyId}; use librespot_core::{Error, Session, SpotifyId, date::Date};
use librespot_protocol as protocol; use librespot_protocol as protocol;
pub use protocol::metadata::episode::EpisodeType; pub use protocol::metadata::episode::EpisodeType;

View file

@ -8,11 +8,11 @@ use crate::util::{impl_deref_wrapped, impl_from_repeated, impl_try_from_repeated
use librespot_core::{FileId, SpotifyId}; use librespot_core::{FileId, SpotifyId};
use librespot_protocol as protocol; use librespot_protocol as protocol;
pub use protocol::metadata::image::Size as ImageSize;
use protocol::metadata::Image as ImageMessage; use protocol::metadata::Image as ImageMessage;
use protocol::metadata::ImageGroup; use protocol::metadata::ImageGroup;
use protocol::playlist4_external::PictureSize as PictureSizeMessage; pub use protocol::metadata::image::Size as ImageSize;
use protocol::playlist_annotate3::TranscodedPicture as TranscodedPictureMessage; use protocol::playlist_annotate3::TranscodedPicture as TranscodedPictureMessage;
use protocol::playlist4_external::PictureSize as PictureSizeMessage;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Image { pub struct Image {

View file

@ -3,9 +3,9 @@ use std::fmt::Debug;
use protobuf::Message; use protobuf::Message;
use crate::{ use crate::{
Metadata,
image::TranscodedPictures, image::TranscodedPictures,
request::{MercuryRequest, RequestResult}, request::{MercuryRequest, RequestResult},
Metadata,
}; };
use librespot_core::{Error, Session, SpotifyId}; use librespot_core::{Error, Session, SpotifyId};

View file

@ -10,7 +10,7 @@ use super::{
permission::Capabilities, permission::Capabilities,
}; };
use librespot_core::{date::Date, SpotifyId}; use librespot_core::{SpotifyId, date::Date};
use librespot_protocol as protocol; use librespot_protocol as protocol;
use protocol::playlist4_external::Item as PlaylistItemMessage; use protocol::playlist4_external::Item as PlaylistItemMessage;

View file

@ -4,9 +4,9 @@ use std::{
}; };
use crate::{ use crate::{
Metadata,
request::RequestResult, request::RequestResult,
util::{impl_deref_wrapped, impl_from_repeated_copy, impl_try_from_repeated}, util::{impl_deref_wrapped, impl_from_repeated_copy, impl_try_from_repeated},
Metadata,
}; };
use super::{ use super::{
@ -15,9 +15,9 @@ use super::{
}; };
use librespot_core::{ use librespot_core::{
Error, Session,
date::Date, date::Date,
spotify_id::{NamedSpotifyId, SpotifyId}, spotify_id::{NamedSpotifyId, SpotifyId},
Error, Session,
}; };
use librespot_protocol as protocol; use librespot_protocol as protocol;

View file

@ -12,11 +12,11 @@ use crate::{
}; };
use librespot_protocol as protocol; use librespot_protocol as protocol;
pub use protocol::playlist4_external::op::Kind as PlaylistOperationKind;
use protocol::playlist4_external::Add as PlaylistAddMessage; use protocol::playlist4_external::Add as PlaylistAddMessage;
use protocol::playlist4_external::Mov as PlaylistMoveMessage; use protocol::playlist4_external::Mov as PlaylistMoveMessage;
use protocol::playlist4_external::Op as PlaylistOperationMessage; use protocol::playlist4_external::Op as PlaylistOperationMessage;
use protocol::playlist4_external::Rem as PlaylistRemoveMessage; use protocol::playlist4_external::Rem as PlaylistRemoveMessage;
pub use protocol::playlist4_external::op::Kind as PlaylistOperationKind;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct PlaylistOperation { pub struct PlaylistOperation {

View file

@ -1,8 +1,8 @@
use std::fmt::Debug; use std::fmt::Debug;
use crate::{ use crate::{
availability::Availabilities, copyright::Copyrights, episode::Episodes, image::Images, Metadata, RequestResult, availability::Availabilities, copyright::Copyrights,
restriction::Restrictions, Metadata, RequestResult, episode::Episodes, image::Images, restriction::Restrictions,
}; };
use librespot_core::{Error, Session, SpotifyId}; use librespot_core::{Error, Session, SpotifyId};

View file

@ -6,6 +6,7 @@ use std::{
use uuid::Uuid; use uuid::Uuid;
use crate::{ use crate::{
Album, Metadata, RequestResult,
artist::{Artists, ArtistsWithRole}, artist::{Artists, ArtistsWithRole},
audio::file::AudioFiles, audio::file::AudioFiles,
availability::Availabilities, availability::Availabilities,
@ -14,10 +15,9 @@ use crate::{
restriction::Restrictions, restriction::Restrictions,
sale_period::SalePeriods, sale_period::SalePeriods,
util::{impl_deref_wrapped, impl_try_from_repeated}, util::{impl_deref_wrapped, impl_try_from_repeated},
Album, Metadata, RequestResult,
}; };
use librespot_core::{date::Date, Error, Session, SpotifyId}; use librespot_core::{Error, Session, SpotifyId, date::Date};
use librespot_protocol as protocol; use librespot_protocol as protocol;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]

View file

@ -14,8 +14,8 @@
use log::{error, info, trace}; use log::{error, info, trace};
use oauth2::basic::BasicTokenType; use oauth2::basic::BasicTokenType;
use oauth2::{ use oauth2::{
basic::BasicClient, AuthUrl, AuthorizationCode, ClientId, CsrfToken, EndpointNotSet, AuthUrl, AuthorizationCode, ClientId, CsrfToken, EndpointNotSet, EndpointSet,
EndpointSet, PkceCodeChallenge, RedirectUrl, Scope, TokenResponse, TokenUrl, PkceCodeChallenge, RedirectUrl, Scope, TokenResponse, TokenUrl, basic::BasicClient,
}; };
use oauth2::{EmptyExtraTokenFields, PkceCodeVerifier, RefreshToken, StandardTokenResponse}; use oauth2::{EmptyExtraTokenFields, PkceCodeVerifier, RefreshToken, StandardTokenResponse};
use std::io; use std::io;

View file

@ -262,7 +262,9 @@ fn open_device(dev_name: &str, format: AudioFormat) -> SinkResult<(PCM, usize)>
} }
} }
} else { } else {
trace!("The device's min reported Buffer size was greater than or equal to its max reported Buffer size."); trace!(
"The device's min reported Buffer size was greater than or equal to its max reported Buffer size."
);
ZERO_FRAMES ZERO_FRAMES
}; };
@ -320,8 +322,12 @@ fn open_device(dev_name: &str, format: AudioFormat) -> SinkResult<(PCM, usize)>
} }
} }
} else { } else {
trace!("The device's min reported Period size was greater than or equal to its max reported Period size,"); trace!(
trace!("or the desired min Period size was greater than or equal to the desired max Period size."); "The device's min reported Period size was greater than or equal to its max reported Period size,"
);
trace!(
"or the desired min Period size was greater than or equal to the desired max Period size."
);
ZERO_FRAMES ZERO_FRAMES
}; };

View file

@ -1,7 +1,7 @@
use gstreamer::{ use gstreamer::{
State,
event::{FlushStart, FlushStop}, event::{FlushStart, FlushStop},
prelude::*, prelude::*,
State,
}; };
use gstreamer as gst; use gstreamer as gst;
@ -14,7 +14,7 @@ use std::sync::Arc;
use super::{Open, Sink, SinkAsBytes, SinkError, SinkResult}; use super::{Open, Sink, SinkAsBytes, SinkError, SinkResult};
use crate::{ use crate::{
config::AudioFormat, convert::Converter, decoder::AudioPacket, NUM_CHANNELS, SAMPLE_RATE, NUM_CHANNELS, SAMPLE_RATE, config::AudioFormat, convert::Converter, decoder::AudioPacket,
}; };
pub struct GstreamerSink { pub struct GstreamerSink {

View file

@ -1,12 +1,12 @@
use super::{Open, Sink, SinkError, SinkResult}; use super::{Open, Sink, SinkError, SinkResult};
use crate::NUM_CHANNELS;
use crate::config::AudioFormat; use crate::config::AudioFormat;
use crate::convert::Converter; use crate::convert::Converter;
use crate::decoder::AudioPacket; use crate::decoder::AudioPacket;
use crate::NUM_CHANNELS;
use jack::{ use jack::{
AsyncClient, AudioOut, Client, ClientOptions, Control, Port, ProcessHandler, ProcessScope, AsyncClient, AudioOut, Client, ClientOptions, Control, Port, ProcessHandler, ProcessScope,
}; };
use std::sync::mpsc::{sync_channel, Receiver, SyncSender}; use std::sync::mpsc::{Receiver, SyncSender, sync_channel};
pub struct JackSink { pub struct JackSink {
send: SyncSender<f32>, send: SyncSender<f32>,

View file

@ -44,7 +44,9 @@ pub struct StdoutSink {
impl Open for StdoutSink { impl Open for StdoutSink {
fn open(file: Option<String>, format: AudioFormat) -> Self { fn open(file: Option<String>, format: AudioFormat) -> Self {
if let Some("?") = file.as_deref() { if let Some("?") = file.as_deref() {
println!("\nUsage:\n\nOutput to stdout:\n\n\t--backend pipe\n\nOutput to file:\n\n\t--backend pipe --device {{filename}}\n"); println!(
"\nUsage:\n\nOutput to stdout:\n\n\t--backend pipe\n\nOutput to file:\n\n\t--backend pipe --device {{filename}}\n"
);
exit(0); exit(0);
} }

View file

@ -3,7 +3,7 @@ use crate::config::AudioFormat;
use crate::convert::Converter; use crate::convert::Converter;
use crate::decoder::AudioPacket; use crate::decoder::AudioPacket;
use crate::{NUM_CHANNELS, SAMPLE_RATE}; use crate::{NUM_CHANNELS, SAMPLE_RATE};
use portaudio_rs::device::{get_default_output_index, DeviceIndex, DeviceInfo}; use portaudio_rs::device::{DeviceIndex, DeviceInfo, get_default_output_index};
use portaudio_rs::stream::*; use portaudio_rs::stream::*;
use std::process::exit; use std::process::exit;
use std::time::Duration; use std::time::Duration;

View file

@ -10,7 +10,9 @@ use thiserror::Error;
#[derive(Debug, Error)] #[derive(Debug, Error)]
enum PulseError { enum PulseError {
#[error("<PulseAudioSink> Unsupported Pulseaudio Sample Spec, Format {pulse_format:?} ({format:?}), Channels {channels}, Rate {rate}")] #[error(
"<PulseAudioSink> Unsupported Pulseaudio Sample Spec, Format {pulse_format:?} ({format:?}), Channels {channels}, Rate {rate}"
)]
InvalidSampleSpec { InvalidSampleSpec {
pulse_format: pulse::sample::Format, pulse_format: pulse::sample::Format,
format: AudioFormat, format: AudioFormat,

View file

@ -5,7 +5,7 @@ use crate::decoder::AudioPacket;
use shell_words::split; use shell_words::split;
use std::io::{ErrorKind, Write}; use std::io::{ErrorKind, Write};
use std::process::{exit, Child, Command, Stdio}; use std::process::{Child, Command, Stdio, exit};
use thiserror::Error; use thiserror::Error;
#[derive(Debug, Error)] #[derive(Debug, Error)]
@ -68,7 +68,9 @@ pub struct SubprocessSink {
impl Open for SubprocessSink { impl Open for SubprocessSink {
fn open(shell_command: Option<String>, format: AudioFormat) -> Self { fn open(shell_command: Option<String>, format: AudioFormat) -> Self {
if let Some("?") = shell_command.as_deref() { if let Some("?") = shell_command.as_deref() {
println!("\nUsage:\n\nOutput to a Subprocess:\n\n\t--backend subprocess --device {{shell_command}}\n"); println!(
"\nUsage:\n\nOutput to a Subprocess:\n\n\t--backend subprocess --device {{shell_command}}\n"
);
exit(0); exit(0);
} }

View file

@ -1,6 +1,6 @@
use std::{mem, str::FromStr, time::Duration}; use std::{mem, str::FromStr, time::Duration};
pub use crate::dither::{mk_ditherer, DithererBuilder, TriangularDitherer}; pub use crate::dither::{DithererBuilder, TriangularDitherer, mk_ditherer};
use crate::{convert::i24, player::duration_to_coefficient}; use crate::{convert::i24, player::duration_to_coefficient};
#[derive(Clone, Copy, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)] #[derive(Clone, Copy, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]

View file

@ -10,8 +10,8 @@ use ogg::{OggReadError, Packet, PacketReader, PacketWriteEndInfo, PacketWriter};
use super::{AudioDecoder, AudioPacket, AudioPacketPosition, DecoderError, DecoderResult}; use super::{AudioDecoder, AudioPacket, AudioPacketPosition, DecoderError, DecoderResult};
use crate::{ use crate::{
metadata::audio::{AudioFileFormat, AudioFiles},
MS_PER_PAGE, PAGES_PER_MS, MS_PER_PAGE, PAGES_PER_MS,
metadata::audio::{AudioFileFormat, AudioFiles},
}; };
fn get_header<T>(code: u8, rdr: &mut PacketReader<T>) -> DecoderResult<Vec<u8>> fn get_header<T>(code: u8, rdr: &mut PacketReader<T>) -> DecoderResult<Vec<u8>>

View file

@ -18,9 +18,9 @@ use symphonia::{
use super::{AudioDecoder, AudioPacket, AudioPacketPosition, DecoderError, DecoderResult}; use super::{AudioDecoder, AudioPacket, AudioPacketPosition, DecoderError, DecoderResult};
use crate::{ use crate::{
NUM_CHANNELS, PAGES_PER_MS, SAMPLE_RATE,
metadata::audio::{AudioFileFormat, AudioFiles}, metadata::audio::{AudioFileFormat, AudioFiles},
player::NormalisationData, player::NormalisationData,
NUM_CHANNELS, PAGES_PER_MS, SAMPLE_RATE,
}; };
pub struct SymphoniaDecoder { pub struct SymphoniaDecoder {

View file

@ -1,5 +1,5 @@
use rand::rngs::SmallRng;
use rand::SeedableRng; use rand::SeedableRng;
use rand::rngs::SmallRng;
use rand_distr::{Distribution, Normal, Triangular, Uniform}; use rand_distr::{Distribution, Normal, Triangular, Uniform};
use std::fmt; use std::fmt;

View file

@ -3,9 +3,9 @@ use crate::player::{db_to_ratio, ratio_to_db};
use super::mappings::{LogMapping, MappedCtrl, VolumeMapping}; use super::mappings::{LogMapping, MappedCtrl, VolumeMapping};
use super::{Mixer, MixerConfig, VolumeCtrl}; use super::{Mixer, MixerConfig, VolumeCtrl};
use alsa::Error as AlsaError;
use alsa::ctl::{ElemId, ElemIface}; use alsa::ctl::{ElemId, ElemIface};
use alsa::mixer::{MilliBel, SelemChannelId, SelemId}; use alsa::mixer::{MilliBel, SelemChannelId, SelemId};
use alsa::Error as AlsaError;
use alsa::{Ctl, Round}; use alsa::{Ctl, Round};
use librespot_core::Error; use librespot_core::Error;
@ -106,7 +106,11 @@ impl Mixer for AlsaMixer {
let reported_step_size = (max_millibel - min_millibel).0 / range; let reported_step_size = (max_millibel - min_millibel).0 / range;
let assumed_step_size = (ZERO_DB - min_millibel).0 / range; let assumed_step_size = (ZERO_DB - min_millibel).0 / range;
if reported_step_size == assumed_step_size { if reported_step_size == assumed_step_size {
warn!("Alsa rounding error detected, setting maximum dB to {:.2} instead of {:.2}", ZERO_DB.to_db(), max_millibel.to_db()); warn!(
"Alsa rounding error detected, setting maximum dB to {:.2} instead of {:.2}",
ZERO_DB.to_db(),
max_millibel.to_db()
);
max_millibel = ZERO_DB; max_millibel = ZERO_DB;
} else { } else {
warn!("Please manually set `--volume-range` if this is incorrect"); warn!("Please manually set `--volume-range` if this is incorrect");

View file

@ -3,8 +3,8 @@ use super::{MappedCtrl, VolumeCtrl};
use super::{Mixer, MixerConfig}; use super::{Mixer, MixerConfig};
use librespot_core::Error; use librespot_core::Error;
use portable_atomic::AtomicU64; use portable_atomic::AtomicU64;
use std::sync::atomic::Ordering;
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::Ordering;
#[derive(Clone)] #[derive(Clone)]
pub struct SoftMixer { pub struct SoftMixer {

View file

@ -7,8 +7,8 @@ use std::{
pin::Pin, pin::Pin,
process::exit, process::exit,
sync::{ sync::{
atomic::{AtomicUsize, Ordering},
Arc, Arc,
atomic::{AtomicUsize, Ordering},
}, },
task::{Context, Poll}, task::{Context, Poll},
thread, thread,
@ -16,8 +16,8 @@ use std::{
}; };
use futures_util::{ use futures_util::{
future, future::FusedFuture, stream::futures_unordered::FuturesUnordered, StreamExt, StreamExt, TryFutureExt, future, future::FusedFuture,
TryFutureExt, stream::futures_unordered::FuturesUnordered,
}; };
use parking_lot::Mutex; use parking_lot::Mutex;
use symphonia::core::io::MediaSource; use symphonia::core::io::MediaSource;
@ -28,7 +28,7 @@ use crate::{
audio_backend::Sink, audio_backend::Sink,
config::{Bitrate, NormalisationMethod, NormalisationType, PlayerConfig}, config::{Bitrate, NormalisationMethod, NormalisationType, PlayerConfig},
convert::Converter, convert::Converter,
core::{util::SeqGenerator, Error, Session, SpotifyId}, core::{Error, Session, SpotifyId, util::SeqGenerator},
decoder::{AudioDecoder, AudioPacket, AudioPacketPosition, SymphoniaDecoder}, decoder::{AudioDecoder, AudioPacket, AudioPacketPosition, SymphoniaDecoder},
metadata::audio::{AudioFileFormat, AudioFiles, AudioItem}, metadata::audio::{AudioFileFormat, AudioFiles, AudioItem},
mixer::VolumeGetter, mixer::VolumeGetter,
@ -1115,7 +1115,9 @@ impl PlayerTrackLoader {
// If the position is invalid just start from // If the position is invalid just start from
// the beginning of the track. // the beginning of the track.
let position_ms = if position_ms > duration_ms { let position_ms = if position_ms > duration_ms {
warn!("Invalid start position of {position_ms} ms exceeds track's duration of {duration_ms} ms, starting track from the beginning"); warn!(
"Invalid start position of {position_ms} ms exceeds track's duration of {duration_ms} ms, starting track from the beginning"
);
0 0
} else { } else {
position_ms position_ms
@ -1351,7 +1353,9 @@ impl Future for PlayerInternal {
} }
} }
Err(e) => { Err(e) => {
error!("Skipping to next track, unable to decode samples for track <{track_id:?}>: {e:?}"); error!(
"Skipping to next track, unable to decode samples for track <{track_id:?}>: {e:?}"
);
self.send_event(PlayerEvent::EndOfTrack { self.send_event(PlayerEvent::EndOfTrack {
track_id, track_id,
play_request_id, play_request_id,
@ -1364,7 +1368,9 @@ impl Future for PlayerInternal {
self.handle_packet(result, normalisation_factor); self.handle_packet(result, normalisation_factor);
} }
Err(e) => { Err(e) => {
error!("Skipping to next track, unable to get next packet for track <{track_id:?}>: {e:?}"); error!(
"Skipping to next track, unable to get next packet for track <{track_id:?}>: {e:?}"
);
self.send_event(PlayerEvent::EndOfTrack { self.send_event(PlayerEvent::EndOfTrack {
track_id, track_id,
play_request_id, play_request_id,
@ -1814,7 +1820,10 @@ impl PlayerInternal {
let mut loaded_track = match mem::replace(&mut self.state, PlayerState::Invalid) { let mut loaded_track = match mem::replace(&mut self.state, PlayerState::Invalid) {
PlayerState::EndOfTrack { loaded_track, .. } => loaded_track, PlayerState::EndOfTrack { loaded_track, .. } => loaded_track,
_ => { _ => {
return Err(Error::internal(format!("PlayerInternal::handle_command_load repeating the same track: invalid state: {:?}", self.state))); return Err(Error::internal(format!(
"PlayerInternal::handle_command_load repeating the same track: invalid state: {:?}",
self.state
)));
} }
}; };
@ -1825,7 +1834,10 @@ impl PlayerInternal {
self.preload = PlayerPreload::None; self.preload = PlayerPreload::None;
self.start_playback(track_id, play_request_id, loaded_track, play); self.start_playback(track_id, play_request_id, loaded_track, play);
if let PlayerState::Invalid = self.state { if let PlayerState::Invalid = self.state {
return Err(Error::internal(format!("PlayerInternal::handle_command_load repeating the same track: start_playback() did not transition to valid player state: {:?}", self.state))); return Err(Error::internal(format!(
"PlayerInternal::handle_command_load repeating the same track: start_playback() did not transition to valid player state: {:?}",
self.state
)));
} }
return Ok(()); return Ok(());
} }
@ -1894,12 +1906,18 @@ impl PlayerInternal {
self.start_playback(track_id, play_request_id, loaded_track, play); self.start_playback(track_id, play_request_id, loaded_track, play);
if let PlayerState::Invalid = self.state { if let PlayerState::Invalid = self.state {
return Err(Error::internal(format!("PlayerInternal::handle_command_load already playing this track: start_playback() did not transition to valid player state: {:?}", self.state))); return Err(Error::internal(format!(
"PlayerInternal::handle_command_load already playing this track: start_playback() did not transition to valid player state: {:?}",
self.state
)));
} }
return Ok(()); return Ok(());
} else { } else {
return Err(Error::internal(format!("PlayerInternal::handle_command_load already playing this track: invalid state: {:?}", self.state))); return Err(Error::internal(format!(
"PlayerInternal::handle_command_load already playing this track: invalid state: {:?}",
self.state
)));
} }
} }
} }
@ -1924,7 +1942,10 @@ impl PlayerInternal {
self.start_playback(track_id, play_request_id, *loaded_track, play); self.start_playback(track_id, play_request_id, *loaded_track, play);
return Ok(()); return Ok(());
} else { } else {
return Err(Error::internal(format!("PlayerInternal::handle_command_loading preloaded track: invalid state: {:?}", self.state))); return Err(Error::internal(format!(
"PlayerInternal::handle_command_loading preloaded track: invalid state: {:?}",
self.state
)));
} }
} }
} }
@ -2180,7 +2201,9 @@ impl PlayerInternal {
} = self.state } = self.state
{ {
if is_explicit { if is_explicit {
warn!("Currently loaded track is explicit, which client setting forbids -- skipping to next track."); warn!(
"Currently loaded track is explicit, which client setting forbids -- skipping to next track."
);
self.send_event(PlayerEvent::EndOfTrack { self.send_event(PlayerEvent::EndOfTrack {
track_id, track_id,
play_request_id, play_request_id,

View file

@ -1 +1,2 @@
edition = "2021" edition = "2024"
style_edition = "2024"