mirror of
https://github.com/librespot-org/librespot.git
synced 2025-10-02 17:29:22 +02:00
style: format with style edition 2024
This commit is contained in:
parent
056d125cb2
commit
218eced556
62 changed files with 196 additions and 139 deletions
|
@ -5,21 +5,21 @@ use std::{
|
|||
fs,
|
||||
io::{self, Read, Seek, SeekFrom},
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
Arc, OnceLock,
|
||||
atomic::{AtomicBool, AtomicUsize, Ordering},
|
||||
},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use futures_util::{future::IntoStream, StreamExt, TryFutureExt};
|
||||
use hyper::{body::Incoming, header::CONTENT_RANGE, Response, StatusCode};
|
||||
use futures_util::{StreamExt, TryFutureExt, future::IntoStream};
|
||||
use hyper::{Response, StatusCode, body::Incoming, header::CONTENT_RANGE};
|
||||
use hyper_util::client::legacy::ResponseFuture;
|
||||
use parking_lot::{Condvar, Mutex};
|
||||
use tempfile::NamedTempFile;
|
||||
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;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ use hyper::StatusCode;
|
|||
use tempfile::NamedTempFile;
|
||||
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};
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::{
|
|||
autoplay_context_request::AutoplayContextRequest, context::Context,
|
||||
transfer_state::TransferState,
|
||||
},
|
||||
state::{context::ContextType, ConnectState},
|
||||
state::{ConnectState, context::ContextType},
|
||||
};
|
||||
use std::{
|
||||
cmp::PartialEq,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use rand::{rngs::SmallRng, Rng, SeedableRng};
|
||||
use rand::{Rng, SeedableRng, rngs::SmallRng};
|
||||
use std::{
|
||||
ops::{Deref, DerefMut},
|
||||
vec::IntoIter,
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use crate::{
|
||||
LoadContextOptions, LoadRequestOptions, PlayContext,
|
||||
context_resolver::{ContextAction, ContextResolver, ResolveContext},
|
||||
core::{
|
||||
Error, Session, SpotifyId,
|
||||
authentication::Credentials,
|
||||
dealer::{
|
||||
manager::{BoxedStream, BoxedStreamResult, Reply, RequestReply},
|
||||
protocol::{Command, FallbackWrapper, Message, Request},
|
||||
},
|
||||
session::UserAttributes,
|
||||
Error, Session, SpotifyId,
|
||||
},
|
||||
model::{LoadRequest, PlayingTrack, SpircPlayStatus},
|
||||
playback::{
|
||||
|
@ -28,15 +29,14 @@ use crate::{
|
|||
provider::IsProvider,
|
||||
{ConnectConfig, ConnectState},
|
||||
},
|
||||
LoadContextOptions, LoadRequestOptions, PlayContext,
|
||||
};
|
||||
use futures_util::StreamExt;
|
||||
use librespot_protocol::context_page::ContextPage;
|
||||
use protobuf::MessageField;
|
||||
use std::{
|
||||
future::Future,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
sync::Arc,
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
time::{Duration, SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
use thiserror::Error;
|
||||
|
@ -951,7 +951,8 @@ impl SpircTask {
|
|||
{
|
||||
debug!(
|
||||
"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 {
|
||||
self.context_resolver.add(ResolveContext::from_context(
|
||||
|
@ -1615,7 +1616,9 @@ impl SpircTask {
|
|||
let uri = String::from_utf8(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(());
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ mod transfer;
|
|||
|
||||
use crate::{
|
||||
core::{
|
||||
config::DeviceType, date::Date, dealer::protocol::Request, spclient::SpClientResult,
|
||||
version, Error, Session,
|
||||
Error, Session, config::DeviceType, date::Date, dealer::protocol::Request,
|
||||
spclient::SpClientResult, version,
|
||||
},
|
||||
model::SpircPlayStatus,
|
||||
protocol::{
|
||||
|
|
|
@ -9,9 +9,9 @@ use crate::{
|
|||
},
|
||||
shuffle_vec::ShuffleVec,
|
||||
state::{
|
||||
ConnectState, SPOTIFY_MAX_NEXT_TRACKS_SIZE, StateError,
|
||||
metadata::Metadata,
|
||||
provider::{IsProvider, Provider},
|
||||
ConnectState, StateError, SPOTIFY_MAX_NEXT_TRACKS_SIZE,
|
||||
},
|
||||
};
|
||||
use protobuf::MessageField;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::{
|
||||
core::{dealer::protocol::SetQueueCommand, Error},
|
||||
core::{Error, dealer::protocol::SetQueueCommand},
|
||||
state::{
|
||||
ConnectState,
|
||||
context::{ContextType, ResetContext},
|
||||
metadata::Metadata,
|
||||
ConnectState,
|
||||
},
|
||||
};
|
||||
use protobuf::MessageField;
|
||||
|
|
|
@ -2,9 +2,9 @@ use crate::{
|
|||
core::Error,
|
||||
protocol::player::ContextPlayerOptions,
|
||||
state::{
|
||||
ConnectState, StateError,
|
||||
context::{ContextType, ResetContext},
|
||||
metadata::Metadata,
|
||||
ConnectState, StateError,
|
||||
},
|
||||
};
|
||||
use protobuf::MessageField;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::state::provider::IsProvider;
|
||||
use crate::state::ConnectState;
|
||||
use crate::state::provider::IsProvider;
|
||||
use librespot_protocol::player::Restrictions;
|
||||
use protobuf::MessageField;
|
||||
|
||||
|
|
|
@ -2,10 +2,10 @@ use crate::{
|
|||
core::{Error, SpotifyId},
|
||||
protocol::player::ProvidedTrack,
|
||||
state::{
|
||||
ConnectState, SPOTIFY_MAX_NEXT_TRACKS_SIZE, SPOTIFY_MAX_PREV_TRACKS_SIZE, StateError,
|
||||
context::ContextType,
|
||||
metadata::Metadata,
|
||||
provider::{IsProvider, Provider},
|
||||
ConnectState, StateError, SPOTIFY_MAX_NEXT_TRACKS_SIZE, SPOTIFY_MAX_PREV_TRACKS_SIZE,
|
||||
},
|
||||
};
|
||||
use protobuf::MessageField;
|
||||
|
|
|
@ -139,7 +139,7 @@ impl ApResolver {
|
|||
_ => {
|
||||
return Err(Error::unimplemented(format!(
|
||||
"No implementation to resolve access point {endpoint}"
|
||||
)))
|
||||
)));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ use bytes::Bytes;
|
|||
use thiserror::Error;
|
||||
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)]
|
||||
pub struct AudioKey(pub [u8; 16]);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use std::io::{self, Read};
|
||||
|
||||
use aes::Aes192;
|
||||
use base64::engine::general_purpose::STANDARD as BASE64;
|
||||
use base64::engine::Engine as _;
|
||||
use base64::engine::general_purpose::STANDARD as BASE64;
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
use pbkdf2::pbkdf2_hmac;
|
||||
use protobuf::Enum;
|
||||
|
@ -10,7 +10,7 @@ use serde::{Deserialize, Serialize};
|
|||
use sha1::{Digest, Sha1};
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{protocol::authentication::AuthenticationType, Error};
|
||||
use crate::{Error, protocol::authentication::AuthenticationType};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum AuthenticationError {
|
||||
|
|
|
@ -12,7 +12,7 @@ use parking_lot::Mutex;
|
|||
use priority_queue::PriorityQueue;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{authentication::Credentials, error::ErrorKind, Error, FileId};
|
||||
use crate::{Error, FileId, authentication::Credentials, error::ErrorKind};
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum CacheError {
|
||||
|
|
|
@ -5,11 +5,11 @@ use thiserror::Error;
|
|||
use time::Duration;
|
||||
use url::Url;
|
||||
|
||||
use super::{date::Date, Error, FileId, Session};
|
||||
use super::{Error, FileId, Session, date::Date};
|
||||
|
||||
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::storage_resolve_response::Result as StorageResolveResponse_Result;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct MaybeExpiringUrl(pub String, pub Option<Date>);
|
||||
|
@ -201,7 +201,9 @@ impl TryFrom<CdnUrlMessage> for MaybeExpiringUrls {
|
|||
expiry = Some(Date::from(with_margin));
|
||||
}
|
||||
} 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 {
|
||||
warn!("Unknown CDN URL format: {cdn_url}");
|
||||
|
@ -225,10 +227,18 @@ mod test {
|
|||
let mut msg = CdnUrlMessage::new();
|
||||
msg.result = StorageResolveResponse_Result::CDN.into();
|
||||
msg.cdnurl = vec![
|
||||
format!("https://audio-cf.spotifycdn.com/audio/844ecdb297a87ebfee4399f28892ef85d9ba725f?verify={timestamp}-4R3I2w2q7OfNkR%2FGH8qH7xtIKUPlDxywBuADY%2BsvMeU%3D"),
|
||||
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="),
|
||||
format!(
|
||||
"https://audio-cf.spotifycdn.com/audio/844ecdb297a87ebfee4399f28892ef85d9ba725f?verify={timestamp}-4R3I2w2q7OfNkR%2FGH8qH7xtIKUPlDxywBuADY%2BsvMeU%3D"
|
||||
),
|
||||
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(),
|
||||
];
|
||||
msg.fileid = vec![0];
|
||||
|
|
|
@ -9,12 +9,12 @@ use std::{
|
|||
use byteorder::{BigEndian, ByteOrder};
|
||||
use bytes::Bytes;
|
||||
use futures_core::Stream;
|
||||
use futures_util::{lock::BiLock, ready, StreamExt};
|
||||
use futures_util::{StreamExt, lock::BiLock, ready};
|
||||
use num_traits::FromPrimitive;
|
||||
use thiserror::Error;
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use crate::{packet::PacketType, util::SeqGenerator, Error};
|
||||
use crate::{Error, packet::PacketType, util::SeqGenerator};
|
||||
|
||||
component! {
|
||||
ChannelManager : ChannelManagerInner {
|
||||
|
|
|
@ -13,7 +13,7 @@ use tokio::net::TcpStream;
|
|||
use tokio_util::codec::Framed;
|
||||
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};
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use std::{fmt::Debug, ops::Deref};
|
||||
|
||||
use time::{
|
||||
error::ComponentRange, format_description::well_known::Iso8601, Date as _Date, OffsetDateTime,
|
||||
PrimitiveDateTime, Time,
|
||||
Date as _Date, OffsetDateTime, PrimitiveDateTime, Time, error::ComponentRange,
|
||||
format_description::well_known::Iso8601,
|
||||
};
|
||||
|
||||
use crate::Error;
|
||||
|
|
|
@ -7,8 +7,8 @@ use tokio_stream::wrappers::UnboundedReceiverStream;
|
|||
use url::Url;
|
||||
|
||||
use super::{
|
||||
protocol::Message, Builder, Dealer, GetUrlResult, Request, RequestHandler, Responder, Response,
|
||||
Subscription,
|
||||
Builder, Dealer, GetUrlResult, Request, RequestHandler, Responder, Response, Subscription,
|
||||
protocol::Message,
|
||||
};
|
||||
use crate::{Error, Session};
|
||||
|
||||
|
|
|
@ -6,22 +6,22 @@ use std::{
|
|||
iter,
|
||||
pin::Pin,
|
||||
sync::{
|
||||
atomic::{self, AtomicBool},
|
||||
Arc,
|
||||
atomic::{self, AtomicBool},
|
||||
},
|
||||
task::Poll,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
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 thiserror::Error;
|
||||
use tokio::{
|
||||
select,
|
||||
sync::{
|
||||
mpsc::{self, UnboundedReceiver},
|
||||
Semaphore,
|
||||
mpsc::{self, UnboundedReceiver},
|
||||
},
|
||||
task::JoinHandle,
|
||||
};
|
||||
|
@ -35,9 +35,8 @@ use self::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
socket,
|
||||
util::{keep_flushing, CancelOnDrop, TimeoutOnDrop},
|
||||
Error,
|
||||
Error, socket,
|
||||
util::{CancelOnDrop, TimeoutOnDrop, keep_flushing},
|
||||
};
|
||||
|
||||
type WsMessage = tungstenite::Message;
|
||||
|
|
|
@ -5,8 +5,8 @@ pub use request::*;
|
|||
use std::collections::HashMap;
|
||||
use std::io::{Error as IoError, Read};
|
||||
|
||||
use crate::{deserialize_with::json_proto, Error};
|
||||
use base64::{prelude::BASE64_STANDARD, DecodeError, Engine};
|
||||
use crate::{Error, deserialize_with::json_proto};
|
||||
use base64::{DecodeError, Engine, prelude::BASE64_STANDARD};
|
||||
use flate2::read::GzDecoder;
|
||||
use log::LevelFilter;
|
||||
use serde::Deserialize;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use base64::prelude::BASE64_STANDARD;
|
||||
use base64::Engine;
|
||||
use base64::prelude::BASE64_STANDARD;
|
||||
use protobuf::MessageFull;
|
||||
use serde::de::{Error, Unexpected};
|
||||
use serde::{Deserialize, Deserializer};
|
||||
|
|
|
@ -15,7 +15,7 @@ use http::{
|
|||
use protobuf::Error as ProtobufError;
|
||||
use thiserror::Error;
|
||||
use tokio::sync::{
|
||||
mpsc::error::SendError, oneshot::error::RecvError, AcquireError, TryAcquireError,
|
||||
AcquireError, TryAcquireError, mpsc::error::SendError, oneshot::error::RecvError,
|
||||
};
|
||||
use url::ParseError;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt;
|
|||
|
||||
use librespot_protocol as protocol;
|
||||
|
||||
use crate::{spotify_id::to_base16, Error};
|
||||
use crate::{Error, spotify_id::to_base16};
|
||||
|
||||
const RAW_LEN: usize = 20;
|
||||
|
||||
|
|
|
@ -5,17 +5,17 @@ use std::{
|
|||
};
|
||||
|
||||
use bytes::Bytes;
|
||||
use futures_util::{future::IntoStream, FutureExt};
|
||||
use futures_util::{FutureExt, future::IntoStream};
|
||||
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 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_rustls::{HttpsConnector, HttpsConnectorBuilder};
|
||||
use hyper_util::{
|
||||
client::legacy::{connect::HttpConnector, Client, ResponseFuture},
|
||||
client::legacy::{Client, ResponseFuture, connect::HttpConnector},
|
||||
rt::TokioExecutor,
|
||||
};
|
||||
use nonzero_ext::nonzero;
|
||||
|
@ -24,10 +24,10 @@ use thiserror::Error;
|
|||
use url::Url;
|
||||
|
||||
use crate::{
|
||||
config::{os_version, OS},
|
||||
date::Date,
|
||||
version::{spotify_version, FALLBACK_USER_AGENT, VERSION_STRING},
|
||||
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
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
use crate::config::OS;
|
||||
use crate::spclient::CLIENT_TOKEN;
|
||||
use crate::token::Token;
|
||||
use crate::{util, Error, SessionConfig};
|
||||
use crate::{Error, SessionConfig, util};
|
||||
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::{
|
||||
client_info::ClientInfo,
|
||||
credentials::{Password, StoredCredential},
|
||||
hashcash::HashcashSolution,
|
||||
login5::{
|
||||
login_request::Login_method, ChallengeSolution, LoginError, LoginOk, LoginRequest,
|
||||
LoginResponse,
|
||||
ChallengeSolution, LoginError, LoginOk, LoginRequest, LoginResponse,
|
||||
login_request::Login_method,
|
||||
},
|
||||
};
|
||||
use protobuf::well_known_types::duration::Duration as ProtoDuration;
|
||||
|
|
|
@ -11,7 +11,7 @@ use futures_util::FutureExt;
|
|||
use protobuf::Message;
|
||||
use tokio::sync::{mpsc, oneshot};
|
||||
|
||||
use crate::{packet::PacketType, protocol, util::SeqGenerator, Error};
|
||||
use crate::{Error, packet::PacketType, protocol, util::SeqGenerator};
|
||||
|
||||
mod types;
|
||||
pub use self::types::*;
|
||||
|
|
|
@ -4,7 +4,7 @@ use byteorder::{BigEndian, WriteBytesExt};
|
|||
use protobuf::Message;
|
||||
use thiserror::Error;
|
||||
|
||||
use crate::{packet::PacketType, protocol, Error};
|
||||
use crate::{Error, packet::PacketType, protocol};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum MercuryMethod {
|
||||
|
|
|
@ -12,6 +12,7 @@ use std::{
|
|||
|
||||
use crate::dealer::manager::DealerManager;
|
||||
use crate::{
|
||||
Error,
|
||||
apresolve::{ApResolver, SocketAddress},
|
||||
audio_key::AudioKeyManager,
|
||||
authentication::Credentials,
|
||||
|
@ -26,7 +27,6 @@ use crate::{
|
|||
protocol::keyexchange::ErrorCode,
|
||||
spclient::SpClient,
|
||||
token::TokenProvider,
|
||||
Error,
|
||||
};
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
use bytes::Bytes;
|
||||
|
@ -40,7 +40,7 @@ use quick_xml::events::Event;
|
|||
use thiserror::Error;
|
||||
use tokio::{
|
||||
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 uuid::Uuid;
|
||||
|
|
|
@ -3,8 +3,9 @@ use std::{
|
|||
time::{Duration, Instant},
|
||||
};
|
||||
|
||||
use crate::config::{os_version, OS};
|
||||
use crate::config::{OS, os_version};
|
||||
use crate::{
|
||||
Error, FileId, SpotifyId,
|
||||
apresolve::SocketAddress,
|
||||
config::SessionConfig,
|
||||
error::ErrorKind,
|
||||
|
@ -21,15 +22,14 @@ use crate::{
|
|||
token::Token,
|
||||
util,
|
||||
version::spotify_semantic_version,
|
||||
Error, FileId, SpotifyId,
|
||||
};
|
||||
use bytes::Bytes;
|
||||
use data_encoding::HEXUPPER_PERMISSIVE;
|
||||
use futures_util::future::IntoStream;
|
||||
use http::{header::HeaderValue, Uri};
|
||||
use http::{Uri, header::HeaderValue};
|
||||
use hyper::{
|
||||
header::{HeaderName, ACCEPT, AUTHORIZATION, CONTENT_TYPE, RANGE},
|
||||
HeaderMap, Method, Request,
|
||||
header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE, HeaderName, RANGE},
|
||||
};
|
||||
use hyper_util::client::legacy::ResponseFuture;
|
||||
use protobuf::{Enum, Message, MessageFull};
|
||||
|
@ -335,7 +335,7 @@ impl SpClient {
|
|||
Some(unknown) => {
|
||||
return Err(Error::unimplemented(format!(
|
||||
"Unknown client token response type: {unknown:?}"
|
||||
)))
|
||||
)));
|
||||
}
|
||||
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 {
|
||||
let length = length.unwrap_or(120);
|
||||
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
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::Error;
|
||||
use byteorder::{BigEndian, ByteOrder};
|
||||
use futures_core::ready;
|
||||
use futures_util::{future, FutureExt, Sink, SinkExt};
|
||||
use futures_util::{FutureExt, Sink, SinkExt, future};
|
||||
use hmac::digest::Digest;
|
||||
use sha1::Sha1;
|
||||
use std::time::{Duration, Instant};
|
||||
|
@ -62,11 +62,12 @@ impl<T: Send + 'static> Future for TimeoutOnDrop<T> {
|
|||
type Output = <JoinHandle<T> as Future>::Output;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let r = ready!(self
|
||||
.handle
|
||||
.as_mut()
|
||||
.expect("Polled after ready")
|
||||
.poll_unpin(cx));
|
||||
let r = ready!(
|
||||
self.handle
|
||||
.as_mut()
|
||||
.expect("Polled after ready")
|
||||
.poll_unpin(cx)
|
||||
);
|
||||
self.handle = None;
|
||||
Poll::Ready(r)
|
||||
}
|
||||
|
|
|
@ -211,7 +211,9 @@ async fn avahi_task(
|
|||
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
|
||||
match stream.next().await {
|
||||
|
|
|
@ -6,13 +6,13 @@ use std::{
|
|||
};
|
||||
|
||||
use aes::cipher::{KeyIvInit, StreamCipher};
|
||||
use base64::engine::general_purpose::STANDARD as BASE64;
|
||||
use base64::engine::Engine as _;
|
||||
use base64::engine::general_purpose::STANDARD as BASE64;
|
||||
use bytes::Bytes;
|
||||
use futures_util::{FutureExt, TryFutureExt};
|
||||
use hmac::{Hmac, Mac};
|
||||
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 log::{debug, error, warn};
|
||||
|
@ -24,7 +24,7 @@ use super::{DiscoveryError, DiscoveryEvent};
|
|||
|
||||
use crate::{
|
||||
core::config::DeviceType,
|
||||
core::{authentication::Credentials, diffie_hellman::DhLocalKeys, Error},
|
||||
core::{Error, authentication::Credentials, diffie_hellman::DhLocalKeys},
|
||||
};
|
||||
|
||||
type Aes128Ctr = ctr::Ctr128BE<aes::Aes128>;
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
Metadata,
|
||||
artist::Artists,
|
||||
availability::Availabilities,
|
||||
copyright::Copyrights,
|
||||
|
@ -14,14 +15,13 @@ use crate::{
|
|||
sale_period::SalePeriods,
|
||||
track::Tracks,
|
||||
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;
|
||||
pub use protocol::metadata::album::Type as AlbumType;
|
||||
use protocol::metadata::Disc as DiscMessage;
|
||||
pub use protocol::metadata::album::Type as AlbumType;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Album {
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
Metadata,
|
||||
album::Albums,
|
||||
availability::Availabilities,
|
||||
external_id::ExternalIds,
|
||||
|
@ -13,7 +14,6 @@ use crate::{
|
|||
sale_period::SalePeriods,
|
||||
track::Tracks,
|
||||
util::{impl_deref_wrapped, impl_from_repeated, impl_try_from_repeated},
|
||||
Metadata,
|
||||
};
|
||||
|
||||
use librespot_core::{Error, Session, SpotifyId};
|
||||
|
@ -294,7 +294,7 @@ impl TryFrom<&ActivityPeriodMessage> for ActivityPeriod {
|
|||
_ => {
|
||||
return Err(librespot_core::Error::failed_precondition(
|
||||
"ActivityPeriod is expected to be either a decade or timespan",
|
||||
))
|
||||
));
|
||||
}
|
||||
};
|
||||
Ok(activity_period)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::fmt::Debug;
|
||||
|
||||
use crate::{
|
||||
Metadata,
|
||||
artist::ArtistsWithRole,
|
||||
availability::{AudioItemAvailability, Availabilities, UnavailabilityReason},
|
||||
episode::Episode,
|
||||
|
@ -8,13 +9,12 @@ use crate::{
|
|||
image::{ImageSize, Images},
|
||||
restriction::Restrictions,
|
||||
track::{Track, Tracks},
|
||||
Metadata,
|
||||
};
|
||||
|
||||
use super::file::AudioFiles;
|
||||
|
||||
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>;
|
||||
|
|
|
@ -6,8 +6,8 @@ use std::{
|
|||
use crate::util::{impl_deref_wrapped, impl_from_repeated};
|
||||
|
||||
use librespot_protocol as protocol;
|
||||
pub use protocol::metadata::copyright::Type as CopyrightType;
|
||||
use protocol::metadata::Copyright as CopyrightMessage;
|
||||
pub use protocol::metadata::copyright::Type as CopyrightType;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Copyright {
|
||||
|
|
|
@ -4,6 +4,7 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
Metadata,
|
||||
audio::file::AudioFiles,
|
||||
availability::Availabilities,
|
||||
content_rating::ContentRatings,
|
||||
|
@ -12,10 +13,9 @@ use crate::{
|
|||
restriction::Restrictions,
|
||||
util::{impl_deref_wrapped, impl_try_from_repeated},
|
||||
video::VideoFiles,
|
||||
Metadata,
|
||||
};
|
||||
|
||||
use librespot_core::{date::Date, Error, Session, SpotifyId};
|
||||
use librespot_core::{Error, Session, SpotifyId, date::Date};
|
||||
|
||||
use librespot_protocol as protocol;
|
||||
pub use protocol::metadata::episode::EpisodeType;
|
||||
|
|
|
@ -8,11 +8,11 @@ use crate::util::{impl_deref_wrapped, impl_from_repeated, impl_try_from_repeated
|
|||
use librespot_core::{FileId, SpotifyId};
|
||||
|
||||
use librespot_protocol as protocol;
|
||||
pub use protocol::metadata::image::Size as ImageSize;
|
||||
use protocol::metadata::Image as ImageMessage;
|
||||
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::playlist4_external::PictureSize as PictureSizeMessage;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Image {
|
||||
|
|
|
@ -3,9 +3,9 @@ use std::fmt::Debug;
|
|||
use protobuf::Message;
|
||||
|
||||
use crate::{
|
||||
Metadata,
|
||||
image::TranscodedPictures,
|
||||
request::{MercuryRequest, RequestResult},
|
||||
Metadata,
|
||||
};
|
||||
|
||||
use librespot_core::{Error, Session, SpotifyId};
|
||||
|
|
|
@ -10,7 +10,7 @@ use super::{
|
|||
permission::Capabilities,
|
||||
};
|
||||
|
||||
use librespot_core::{date::Date, SpotifyId};
|
||||
use librespot_core::{SpotifyId, date::Date};
|
||||
|
||||
use librespot_protocol as protocol;
|
||||
use protocol::playlist4_external::Item as PlaylistItemMessage;
|
||||
|
|
|
@ -4,9 +4,9 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
Metadata,
|
||||
request::RequestResult,
|
||||
util::{impl_deref_wrapped, impl_from_repeated_copy, impl_try_from_repeated},
|
||||
Metadata,
|
||||
};
|
||||
|
||||
use super::{
|
||||
|
@ -15,9 +15,9 @@ use super::{
|
|||
};
|
||||
|
||||
use librespot_core::{
|
||||
Error, Session,
|
||||
date::Date,
|
||||
spotify_id::{NamedSpotifyId, SpotifyId},
|
||||
Error, Session,
|
||||
};
|
||||
|
||||
use librespot_protocol as protocol;
|
||||
|
|
|
@ -12,11 +12,11 @@ use crate::{
|
|||
};
|
||||
|
||||
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::Mov as PlaylistMoveMessage;
|
||||
use protocol::playlist4_external::Op as PlaylistOperationMessage;
|
||||
use protocol::playlist4_external::Rem as PlaylistRemoveMessage;
|
||||
pub use protocol::playlist4_external::op::Kind as PlaylistOperationKind;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PlaylistOperation {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use std::fmt::Debug;
|
||||
|
||||
use crate::{
|
||||
availability::Availabilities, copyright::Copyrights, episode::Episodes, image::Images,
|
||||
restriction::Restrictions, Metadata, RequestResult,
|
||||
Metadata, RequestResult, availability::Availabilities, copyright::Copyrights,
|
||||
episode::Episodes, image::Images, restriction::Restrictions,
|
||||
};
|
||||
|
||||
use librespot_core::{Error, Session, SpotifyId};
|
||||
|
|
|
@ -6,6 +6,7 @@ use std::{
|
|||
use uuid::Uuid;
|
||||
|
||||
use crate::{
|
||||
Album, Metadata, RequestResult,
|
||||
artist::{Artists, ArtistsWithRole},
|
||||
audio::file::AudioFiles,
|
||||
availability::Availabilities,
|
||||
|
@ -14,10 +15,9 @@ use crate::{
|
|||
restriction::Restrictions,
|
||||
sale_period::SalePeriods,
|
||||
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;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
use log::{error, info, trace};
|
||||
use oauth2::basic::BasicTokenType;
|
||||
use oauth2::{
|
||||
basic::BasicClient, AuthUrl, AuthorizationCode, ClientId, CsrfToken, EndpointNotSet,
|
||||
EndpointSet, PkceCodeChallenge, RedirectUrl, Scope, TokenResponse, TokenUrl,
|
||||
AuthUrl, AuthorizationCode, ClientId, CsrfToken, EndpointNotSet, EndpointSet,
|
||||
PkceCodeChallenge, RedirectUrl, Scope, TokenResponse, TokenUrl, basic::BasicClient,
|
||||
};
|
||||
use oauth2::{EmptyExtraTokenFields, PkceCodeVerifier, RefreshToken, StandardTokenResponse};
|
||||
use std::io;
|
||||
|
|
|
@ -262,7 +262,9 @@ fn open_device(dev_name: &str, format: AudioFormat) -> SinkResult<(PCM, usize)>
|
|||
}
|
||||
}
|
||||
} 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
|
||||
};
|
||||
|
||||
|
@ -320,8 +322,12 @@ fn open_device(dev_name: &str, format: AudioFormat) -> SinkResult<(PCM, usize)>
|
|||
}
|
||||
}
|
||||
} else {
|
||||
trace!("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.");
|
||||
trace!(
|
||||
"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
|
||||
};
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use gstreamer::{
|
||||
State,
|
||||
event::{FlushStart, FlushStop},
|
||||
prelude::*,
|
||||
State,
|
||||
};
|
||||
|
||||
use gstreamer as gst;
|
||||
|
@ -14,7 +14,7 @@ use std::sync::Arc;
|
|||
use super::{Open, Sink, SinkAsBytes, SinkError, SinkResult};
|
||||
|
||||
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 {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use super::{Open, Sink, SinkError, SinkResult};
|
||||
use crate::NUM_CHANNELS;
|
||||
use crate::config::AudioFormat;
|
||||
use crate::convert::Converter;
|
||||
use crate::decoder::AudioPacket;
|
||||
use crate::NUM_CHANNELS;
|
||||
use jack::{
|
||||
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 {
|
||||
send: SyncSender<f32>,
|
||||
|
|
|
@ -44,7 +44,9 @@ pub struct StdoutSink {
|
|||
impl Open for StdoutSink {
|
||||
fn open(file: Option<String>, format: AudioFormat) -> Self {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::config::AudioFormat;
|
|||
use crate::convert::Converter;
|
||||
use crate::decoder::AudioPacket;
|
||||
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 std::process::exit;
|
||||
use std::time::Duration;
|
||||
|
|
|
@ -10,7 +10,9 @@ use thiserror::Error;
|
|||
|
||||
#[derive(Debug, Error)]
|
||||
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 {
|
||||
pulse_format: pulse::sample::Format,
|
||||
format: AudioFormat,
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::decoder::AudioPacket;
|
|||
use shell_words::split;
|
||||
|
||||
use std::io::{ErrorKind, Write};
|
||||
use std::process::{exit, Child, Command, Stdio};
|
||||
use std::process::{Child, Command, Stdio, exit};
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
|
@ -68,7 +68,9 @@ pub struct SubprocessSink {
|
|||
impl Open for SubprocessSink {
|
||||
fn open(shell_command: Option<String>, format: AudioFormat) -> Self {
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
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};
|
||||
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
|
||||
|
|
|
@ -10,8 +10,8 @@ use ogg::{OggReadError, Packet, PacketReader, PacketWriteEndInfo, PacketWriter};
|
|||
use super::{AudioDecoder, AudioPacket, AudioPacketPosition, DecoderError, DecoderResult};
|
||||
|
||||
use crate::{
|
||||
metadata::audio::{AudioFileFormat, AudioFiles},
|
||||
MS_PER_PAGE, PAGES_PER_MS,
|
||||
metadata::audio::{AudioFileFormat, AudioFiles},
|
||||
};
|
||||
|
||||
fn get_header<T>(code: u8, rdr: &mut PacketReader<T>) -> DecoderResult<Vec<u8>>
|
||||
|
|
|
@ -18,9 +18,9 @@ use symphonia::{
|
|||
use super::{AudioDecoder, AudioPacket, AudioPacketPosition, DecoderError, DecoderResult};
|
||||
|
||||
use crate::{
|
||||
NUM_CHANNELS, PAGES_PER_MS, SAMPLE_RATE,
|
||||
metadata::audio::{AudioFileFormat, AudioFiles},
|
||||
player::NormalisationData,
|
||||
NUM_CHANNELS, PAGES_PER_MS, SAMPLE_RATE,
|
||||
};
|
||||
|
||||
pub struct SymphoniaDecoder {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use rand::rngs::SmallRng;
|
||||
use rand::SeedableRng;
|
||||
use rand::rngs::SmallRng;
|
||||
use rand_distr::{Distribution, Normal, Triangular, Uniform};
|
||||
use std::fmt;
|
||||
|
||||
|
|
|
@ -3,9 +3,9 @@ use crate::player::{db_to_ratio, ratio_to_db};
|
|||
use super::mappings::{LogMapping, MappedCtrl, VolumeMapping};
|
||||
use super::{Mixer, MixerConfig, VolumeCtrl};
|
||||
|
||||
use alsa::Error as AlsaError;
|
||||
use alsa::ctl::{ElemId, ElemIface};
|
||||
use alsa::mixer::{MilliBel, SelemChannelId, SelemId};
|
||||
use alsa::Error as AlsaError;
|
||||
use alsa::{Ctl, Round};
|
||||
|
||||
use librespot_core::Error;
|
||||
|
@ -106,7 +106,11 @@ impl Mixer for AlsaMixer {
|
|||
let reported_step_size = (max_millibel - min_millibel).0 / range;
|
||||
let assumed_step_size = (ZERO_DB - min_millibel).0 / range;
|
||||
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;
|
||||
} else {
|
||||
warn!("Please manually set `--volume-range` if this is incorrect");
|
||||
|
|
|
@ -3,8 +3,8 @@ use super::{MappedCtrl, VolumeCtrl};
|
|||
use super::{Mixer, MixerConfig};
|
||||
use librespot_core::Error;
|
||||
use portable_atomic::AtomicU64;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::Arc;
|
||||
use std::sync::atomic::Ordering;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SoftMixer {
|
||||
|
|
|
@ -7,8 +7,8 @@ use std::{
|
|||
pin::Pin,
|
||||
process::exit,
|
||||
sync::{
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
Arc,
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
},
|
||||
task::{Context, Poll},
|
||||
thread,
|
||||
|
@ -16,8 +16,8 @@ use std::{
|
|||
};
|
||||
|
||||
use futures_util::{
|
||||
future, future::FusedFuture, stream::futures_unordered::FuturesUnordered, StreamExt,
|
||||
TryFutureExt,
|
||||
StreamExt, TryFutureExt, future, future::FusedFuture,
|
||||
stream::futures_unordered::FuturesUnordered,
|
||||
};
|
||||
use parking_lot::Mutex;
|
||||
use symphonia::core::io::MediaSource;
|
||||
|
@ -28,7 +28,7 @@ use crate::{
|
|||
audio_backend::Sink,
|
||||
config::{Bitrate, NormalisationMethod, NormalisationType, PlayerConfig},
|
||||
convert::Converter,
|
||||
core::{util::SeqGenerator, Error, Session, SpotifyId},
|
||||
core::{Error, Session, SpotifyId, util::SeqGenerator},
|
||||
decoder::{AudioDecoder, AudioPacket, AudioPacketPosition, SymphoniaDecoder},
|
||||
metadata::audio::{AudioFileFormat, AudioFiles, AudioItem},
|
||||
mixer::VolumeGetter,
|
||||
|
@ -1115,7 +1115,9 @@ impl PlayerTrackLoader {
|
|||
// If the position is invalid just start from
|
||||
// the beginning of the track.
|
||||
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
|
||||
} else {
|
||||
position_ms
|
||||
|
@ -1351,7 +1353,9 @@ impl Future for PlayerInternal {
|
|||
}
|
||||
}
|
||||
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 {
|
||||
track_id,
|
||||
play_request_id,
|
||||
|
@ -1364,7 +1368,9 @@ impl Future for PlayerInternal {
|
|||
self.handle_packet(result, normalisation_factor);
|
||||
}
|
||||
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 {
|
||||
track_id,
|
||||
play_request_id,
|
||||
|
@ -1814,7 +1820,10 @@ impl PlayerInternal {
|
|||
let mut loaded_track = match mem::replace(&mut self.state, PlayerState::Invalid) {
|
||||
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.start_playback(track_id, play_request_id, loaded_track, play);
|
||||
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(());
|
||||
}
|
||||
|
@ -1894,12 +1906,18 @@ impl PlayerInternal {
|
|||
self.start_playback(track_id, play_request_id, loaded_track, play);
|
||||
|
||||
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(());
|
||||
} 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);
|
||||
return Ok(());
|
||||
} 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
|
||||
{
|
||||
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 {
|
||||
track_id,
|
||||
play_request_id,
|
||||
|
|
|
@ -1 +1,2 @@
|
|||
edition = "2021"
|
||||
edition = "2024"
|
||||
style_edition = "2024"
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue