mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Fix newly reported clippy errors
- Use variables directly in format strings. As reported by clippy, variables can be used directly in the `format!` string. - Use rewind() instead of seeking to 0. - Remove superfluous & and ref. Signed-off-by: Petr Tesarik <petr@tesarici.cz>
This commit is contained in:
parent
e9dbdfed25
commit
c600297f52
19 changed files with 69 additions and 90 deletions
|
@ -62,7 +62,7 @@ async fn receive_data(
|
||||||
Some(Err(e)) => break Err(e.into()),
|
Some(Err(e)) => break Err(e.into()),
|
||||||
None => {
|
None => {
|
||||||
if actual_length != request.length {
|
if actual_length != request.length {
|
||||||
let msg = format!("did not expect body to contain {} bytes", actual_length);
|
let msg = format!("did not expect body to contain {actual_length} bytes");
|
||||||
break Err(Error::data_loss(msg));
|
break Err(Error::data_loss(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,7 +385,7 @@ impl AudioFileFetch {
|
||||||
let complete_tx = self.complete_tx.take();
|
let complete_tx = self.complete_tx.take();
|
||||||
|
|
||||||
if let Some(mut output) = output {
|
if let Some(mut output) = output {
|
||||||
output.seek(SeekFrom::Start(0))?;
|
output.rewind()?;
|
||||||
if let Some(complete_tx) = complete_tx {
|
if let Some(complete_tx) = complete_tx {
|
||||||
complete_tx
|
complete_tx
|
||||||
.send(output)
|
.send(output)
|
||||||
|
|
|
@ -35,7 +35,7 @@ impl fmt::Display for RangeSet {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "(")?;
|
write!(f, "(")?;
|
||||||
for range in self.ranges.iter() {
|
for range in self.ranges.iter() {
|
||||||
write!(f, "{}", range)?;
|
write!(f, "{range}")?;
|
||||||
}
|
}
|
||||||
write!(f, ")")
|
write!(f, ")")
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,5 +22,5 @@ fn main() {
|
||||||
.collect(),
|
.collect(),
|
||||||
};
|
};
|
||||||
|
|
||||||
println!("cargo:rustc-env=LIBRESPOT_BUILD_ID={}", build_id);
|
println!("cargo:rustc-env=LIBRESPOT_BUILD_ID={build_id}");
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,17 +137,13 @@ impl ApResolver {
|
||||||
"spclient" => inner.data.spclient.pop_front(),
|
"spclient" => inner.data.spclient.pop_front(),
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::unimplemented(format!(
|
return Err(Error::unimplemented(format!(
|
||||||
"No implementation to resolve access point {}",
|
"No implementation to resolve access point {endpoint}"
|
||||||
endpoint
|
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let access_point = access_point.ok_or_else(|| {
|
let access_point = access_point.ok_or_else(|| {
|
||||||
Error::unavailable(format!(
|
Error::unavailable(format!("No access point available for endpoint {endpoint}"))
|
||||||
"No access point available for endpoint {}",
|
|
||||||
endpoint
|
|
||||||
))
|
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
Ok(access_point)
|
Ok(access_point)
|
||||||
|
|
|
@ -328,7 +328,7 @@ impl Cache {
|
||||||
if let Some(location) = &self.credentials_location {
|
if let Some(location) = &self.credentials_location {
|
||||||
let result = File::create(location).and_then(|mut file| {
|
let result = File::create(location).and_then(|mut file| {
|
||||||
let data = serde_json::to_string(cred)?;
|
let data = serde_json::to_string(cred)?;
|
||||||
write!(file, "{}", data)
|
write!(file, "{data}")
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
|
@ -360,7 +360,7 @@ impl Cache {
|
||||||
|
|
||||||
pub fn save_volume(&self, volume: u16) {
|
pub fn save_volume(&self, volume: u16) {
|
||||||
if let Some(ref location) = self.volume_location {
|
if let Some(ref location) = self.volume_location {
|
||||||
let result = File::create(location).and_then(|mut file| write!(file, "{}", volume));
|
let result = File::create(location).and_then(|mut file| write!(file, "{volume}"));
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
warn!("Cannot save volume to cache: {}", e);
|
warn!("Cannot save volume to cache: {}", e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,7 +263,7 @@ impl MercuryManager {
|
||||||
let mut found = false;
|
let mut found = false;
|
||||||
|
|
||||||
self.lock(|inner| {
|
self.lock(|inner| {
|
||||||
inner.subscriptions.retain(|&(ref prefix, ref sub)| {
|
inner.subscriptions.retain(|(prefix, sub)| {
|
||||||
if encoded_uri.starts_with(prefix) {
|
if encoded_uri.starts_with(prefix) {
|
||||||
found = true;
|
found = true;
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub async fn proxy_connect<T: AsyncRead + AsyncWrite + Unpin>(
|
||||||
Some(200) => Ok(proxy_connection), // Proxy says all is well
|
Some(200) => Ok(proxy_connection), // Proxy says all is well
|
||||||
Some(code) => {
|
Some(code) => {
|
||||||
let reason = response.reason.unwrap_or("no reason");
|
let reason = response.reason.unwrap_or("no reason");
|
||||||
let msg = format!("Proxy responded with {}: {}", code, reason);
|
let msg = format!("Proxy responded with {code}: {reason}");
|
||||||
Err(io::Error::new(io::ErrorKind::Other, msg))
|
Err(io::Error::new(io::ErrorKind::Other, msg))
|
||||||
}
|
}
|
||||||
None => Err(io::Error::new(
|
None => Err(io::Error::new(
|
||||||
|
|
|
@ -125,8 +125,7 @@ impl SpClient {
|
||||||
let suffix = loop {
|
let suffix = loop {
|
||||||
if now.elapsed().as_secs() >= TIMEOUT {
|
if now.elapsed().as_secs() >= TIMEOUT {
|
||||||
return Err(Error::deadline_exceeded(format!(
|
return Err(Error::deadline_exceeded(format!(
|
||||||
"{} seconds expired",
|
"{TIMEOUT} seconds expired"
|
||||||
TIMEOUT
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,8 +281,7 @@ impl SpClient {
|
||||||
let ctx = vec![];
|
let ctx = vec![];
|
||||||
let prefix = hex::decode(&hash_cash_challenge.prefix).map_err(|e| {
|
let prefix = hex::decode(&hash_cash_challenge.prefix).map_err(|e| {
|
||||||
Error::failed_precondition(format!(
|
Error::failed_precondition(format!(
|
||||||
"Unable to decode hash cash challenge: {}",
|
"Unable to decode hash cash challenge: {e}"
|
||||||
e
|
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
let length = hash_cash_challenge.length;
|
let length = hash_cash_challenge.length;
|
||||||
|
@ -339,8 +337,7 @@ impl SpClient {
|
||||||
response = self.client_token_request(&request).await?;
|
response = self.client_token_request(&request).await?;
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::failed_precondition(format!(
|
return Err(Error::failed_precondition(format!(
|
||||||
"Unable to solve any of {} hash cash challenges",
|
"Unable to solve any of {MAX_TRIES} hash cash challenges"
|
||||||
MAX_TRIES
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -350,8 +347,7 @@ impl SpClient {
|
||||||
|
|
||||||
Some(unknown) => {
|
Some(unknown) => {
|
||||||
return Err(Error::unimplemented(format!(
|
return Err(Error::unimplemented(format!(
|
||||||
"Unknown client token response type: {:?}",
|
"Unknown client token response type: {unknown:?}"
|
||||||
unknown
|
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
None => return Err(Error::failed_precondition("No client token response type")),
|
None => return Err(Error::failed_precondition("No client token response type")),
|
||||||
|
@ -595,20 +591,20 @@ impl SpClient {
|
||||||
playlist_limit: Option<u32>,
|
playlist_limit: Option<u32>,
|
||||||
artist_limit: Option<u32>,
|
artist_limit: Option<u32>,
|
||||||
) -> SpClientResult {
|
) -> SpClientResult {
|
||||||
let mut endpoint = format!("/user-profile-view/v3/profile/{}", username);
|
let mut endpoint = format!("/user-profile-view/v3/profile/{username}");
|
||||||
|
|
||||||
if playlist_limit.is_some() || artist_limit.is_some() {
|
if playlist_limit.is_some() || artist_limit.is_some() {
|
||||||
let _ = write!(endpoint, "?");
|
let _ = write!(endpoint, "?");
|
||||||
|
|
||||||
if let Some(limit) = playlist_limit {
|
if let Some(limit) = playlist_limit {
|
||||||
let _ = write!(endpoint, "playlist_limit={}", limit);
|
let _ = write!(endpoint, "playlist_limit={limit}");
|
||||||
if artist_limit.is_some() {
|
if artist_limit.is_some() {
|
||||||
let _ = write!(endpoint, "&");
|
let _ = write!(endpoint, "&");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(limit) = artist_limit {
|
if let Some(limit) = artist_limit {
|
||||||
let _ = write!(endpoint, "artist_limit={}", limit);
|
let _ = write!(endpoint, "artist_limit={limit}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,14 +613,14 @@ impl SpClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_user_followers(&self, username: &str) -> SpClientResult {
|
pub async fn get_user_followers(&self, username: &str) -> SpClientResult {
|
||||||
let endpoint = format!("/user-profile-view/v3/profile/{}/followers", username);
|
let endpoint = format!("/user-profile-view/v3/profile/{username}/followers");
|
||||||
|
|
||||||
self.request_as_json(&Method::GET, &endpoint, None, None)
|
self.request_as_json(&Method::GET, &endpoint, None, None)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_user_following(&self, username: &str) -> SpClientResult {
|
pub async fn get_user_following(&self, username: &str) -> SpClientResult {
|
||||||
let endpoint = format!("/user-profile-view/v3/profile/{}/following", username);
|
let endpoint = format!("/user-profile-view/v3/profile/{username}/following");
|
||||||
|
|
||||||
self.request_as_json(&Method::GET, &endpoint, None, None)
|
self.request_as_json(&Method::GET, &endpoint, None, None)
|
||||||
.await
|
.await
|
||||||
|
@ -657,14 +653,11 @@ impl SpClient {
|
||||||
previous_tracks: Vec<SpotifyId>,
|
previous_tracks: Vec<SpotifyId>,
|
||||||
autoplay: bool,
|
autoplay: bool,
|
||||||
) -> SpClientResult {
|
) -> SpClientResult {
|
||||||
let mut endpoint = format!(
|
let mut endpoint = format!("/radio-apollo/v3/{scope}/{context_uri}?autoplay={autoplay}");
|
||||||
"/radio-apollo/v3/{}/{}?autoplay={}",
|
|
||||||
scope, context_uri, autoplay,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Spotify has a default of 50
|
// Spotify has a default of 50
|
||||||
if let Some(count) = count {
|
if let Some(count) = count {
|
||||||
let _ = write!(endpoint, "&count={}", count);
|
let _ = write!(endpoint, "&count={count}");
|
||||||
}
|
}
|
||||||
|
|
||||||
let previous_track_str = previous_tracks
|
let previous_track_str = previous_tracks
|
||||||
|
@ -674,7 +667,7 @@ impl SpClient {
|
||||||
.join(",");
|
.join(",");
|
||||||
// better than checking `previous_tracks.len() > 0` because the `filter_map` could still return 0 items
|
// better than checking `previous_tracks.len() > 0` because the `filter_map` could still return 0 items
|
||||||
if !previous_track_str.is_empty() {
|
if !previous_track_str.is_empty() {
|
||||||
let _ = write!(endpoint, "&prev_tracks={}", previous_track_str);
|
let _ = write!(endpoint, "&prev_tracks={previous_track_str}");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.request_as_json(&Method::GET, &endpoint, None, None)
|
self.request_as_json(&Method::GET, &endpoint, None, None)
|
||||||
|
|
|
@ -15,10 +15,10 @@ pub trait MercuryRequest {
|
||||||
Some(_) => "&",
|
Some(_) => "&",
|
||||||
None => "?",
|
None => "?",
|
||||||
};
|
};
|
||||||
let _ = write!(metrics_uri, "{}country={}", separator, session.country());
|
let _ = write!(metrics_uri, "{separator}country={}", session.country());
|
||||||
|
|
||||||
if let Some(product) = session.get_user_attribute("type") {
|
if let Some(product) = session.get_user_attribute("type") {
|
||||||
let _ = write!(metrics_uri, "&product={}", product);
|
let _ = write!(metrics_uri, "&product={product}");
|
||||||
}
|
}
|
||||||
|
|
||||||
trace!("Requesting {}", metrics_uri);
|
trace!("Requesting {}", metrics_uri);
|
||||||
|
@ -28,7 +28,7 @@ pub trait MercuryRequest {
|
||||||
match response.payload.first() {
|
match response.payload.first() {
|
||||||
Some(data) => {
|
Some(data) => {
|
||||||
let data = data.to_vec().into();
|
let data = data.to_vec().into();
|
||||||
trace!("Received metadata: {:?}", data);
|
trace!("Received metadata: {data:?}");
|
||||||
Ok(data)
|
Ok(data)
|
||||||
}
|
}
|
||||||
None => Err(Error::unavailable(MetadataError::Empty)),
|
None => Err(Error::unavailable(MetadataError::Empty)),
|
||||||
|
|
|
@ -131,12 +131,12 @@ fn list_compatible_devices() -> SinkResult<()> {
|
||||||
AudioFormat::F64,
|
AudioFormat::F64,
|
||||||
] {
|
] {
|
||||||
if hwp.test_format(Format::from(*f)).is_ok() {
|
if hwp.test_format(Format::from(*f)).is_ok() {
|
||||||
supported_formats.push(format!("{:?}", f));
|
supported_formats.push(format!("{f:?}"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !supported_formats.is_empty() {
|
if !supported_formats.is_empty() {
|
||||||
println!("\tDevice:\n\n\t\t{}\n", name);
|
println!("\tDevice:\n\n\t\t{name}\n");
|
||||||
|
|
||||||
println!(
|
println!(
|
||||||
"\tDescription:\n\n\t\t{}\n",
|
"\tDescription:\n\n\t\t{}\n",
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub struct GstreamerSink {
|
||||||
|
|
||||||
impl Open for GstreamerSink {
|
impl Open for GstreamerSink {
|
||||||
fn open(device: Option<String>, format: AudioFormat) -> Self {
|
fn open(device: Option<String>, format: AudioFormat) -> Self {
|
||||||
info!("Using GStreamer sink with format: {:?}", format);
|
info!("Using GStreamer sink with format: {format:?}");
|
||||||
gst::init().expect("failed to init GStreamer!");
|
gst::init().expect("failed to init GStreamer!");
|
||||||
|
|
||||||
let gst_format = match format {
|
let gst_format = match format {
|
||||||
|
|
|
@ -40,7 +40,7 @@ impl ProcessHandler for JackData {
|
||||||
impl Open for JackSink {
|
impl Open for JackSink {
|
||||||
fn open(client_name: Option<String>, format: AudioFormat) -> Self {
|
fn open(client_name: Option<String>, format: AudioFormat) -> Self {
|
||||||
if format != AudioFormat::F32 {
|
if format != AudioFormat::F32 {
|
||||||
warn!("JACK currently does not support {:?} output", format);
|
warn!("JACK currently does not support {format:?} output");
|
||||||
}
|
}
|
||||||
info!("Using JACK sink with format {:?}", AudioFormat::F32);
|
info!("Using JACK sink with format {:?}", AudioFormat::F32);
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ fn output_devices() -> Box<dyn Iterator<Item = (DeviceIndex, DeviceInfo)>> {
|
||||||
let count = portaudio_rs::device::get_count().unwrap();
|
let count = portaudio_rs::device::get_count().unwrap();
|
||||||
let devices = (0..count)
|
let devices = (0..count)
|
||||||
.filter_map(|idx| portaudio_rs::device::get_info(idx).map(|info| (idx, info)))
|
.filter_map(|idx| portaudio_rs::device::get_info(idx).map(|info| (idx, info)))
|
||||||
.filter(|&(_, ref info)| info.max_output_channels > 0);
|
.filter(|(_, info)| info.max_output_channels > 0);
|
||||||
|
|
||||||
Box::new(devices)
|
Box::new(devices)
|
||||||
}
|
}
|
||||||
|
@ -46,13 +46,13 @@ fn list_outputs() {
|
||||||
|
|
||||||
fn find_output(device: &str) -> Option<DeviceIndex> {
|
fn find_output(device: &str) -> Option<DeviceIndex> {
|
||||||
output_devices()
|
output_devices()
|
||||||
.find(|&(_, ref info)| info.name == device)
|
.find(|(_, info)| info.name == device)
|
||||||
.map(|(idx, _)| idx)
|
.map(|(idx, _)| idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Open for PortAudioSink<'a> {
|
impl<'a> Open for PortAudioSink<'a> {
|
||||||
fn open(device: Option<String>, format: AudioFormat) -> PortAudioSink<'a> {
|
fn open(device: Option<String>, format: AudioFormat) -> PortAudioSink<'a> {
|
||||||
info!("Using PortAudio sink with format: {:?}", format);
|
info!("Using PortAudio sink with format: {format:?}");
|
||||||
|
|
||||||
portaudio_rs::initialize().unwrap();
|
portaudio_rs::initialize().unwrap();
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ impl<'a> Open for PortAudioSink<'a> {
|
||||||
AudioFormat::S32 => open_sink!(Self::S32, i32),
|
AudioFormat::S32 => open_sink!(Self::S32, i32),
|
||||||
AudioFormat::S16 => open_sink!(Self::S16, i16),
|
AudioFormat::S16 => open_sink!(Self::S16, i16),
|
||||||
_ => {
|
_ => {
|
||||||
unimplemented!("PortAudio currently does not support {:?} output", format)
|
unimplemented!("PortAudio currently does not support {format:?} output")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,7 +168,7 @@ impl<'a> Sink for PortAudioSink<'a> {
|
||||||
match result {
|
match result {
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(portaudio_rs::PaError::OutputUnderflowed) => error!("PortAudio write underflow"),
|
Err(portaudio_rs::PaError::OutputUnderflowed) => error!("PortAudio write underflow"),
|
||||||
Err(e) => panic!("PortAudio error {}", e),
|
Err(e) => panic!("PortAudio error {e}"),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -64,7 +64,7 @@ impl Open for PulseAudioSink {
|
||||||
actual_format = AudioFormat::F32;
|
actual_format = AudioFormat::F32;
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("Using PulseAudioSink with format: {:?}", actual_format);
|
info!("Using PulseAudioSink with format: {actual_format:?}");
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
sink: None,
|
sink: None,
|
||||||
|
|
|
@ -69,11 +69,11 @@ fn list_formats(device: &rodio::Device) {
|
||||||
match device.default_output_config() {
|
match device.default_output_config() {
|
||||||
Ok(cfg) => {
|
Ok(cfg) => {
|
||||||
debug!(" Default config:");
|
debug!(" Default config:");
|
||||||
debug!(" {:?}", cfg);
|
debug!(" {cfg:?}");
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
// Use loglevel debug, since even the output is only debug
|
// Use loglevel debug, since even the output is only debug
|
||||||
debug!("Error getting default rodio::Sink config: {}", e);
|
debug!("Error getting default rodio::Sink config: {e}");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -81,17 +81,17 @@ fn list_formats(device: &rodio::Device) {
|
||||||
Ok(mut cfgs) => {
|
Ok(mut cfgs) => {
|
||||||
if let Some(first) = cfgs.next() {
|
if let Some(first) = cfgs.next() {
|
||||||
debug!(" Available configs:");
|
debug!(" Available configs:");
|
||||||
debug!(" {:?}", first);
|
debug!(" {first:?}");
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for cfg in cfgs {
|
for cfg in cfgs {
|
||||||
debug!(" {:?}", cfg);
|
debug!(" {cfg:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
debug!("Error getting supported rodio::Sink configs: {}", e);
|
debug!("Error getting supported rodio::Sink configs: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,11 +117,11 @@ fn list_outputs(host: &cpal::Host) -> Result<(), cpal::DevicesError> {
|
||||||
match device.name() {
|
match device.name() {
|
||||||
Ok(name) if Some(&name) == default_device_name.as_ref() => (),
|
Ok(name) if Some(&name) == default_device_name.as_ref() => (),
|
||||||
Ok(name) => {
|
Ok(name) => {
|
||||||
println!(" {}", name);
|
println!(" {name}");
|
||||||
list_formats(&device);
|
list_formats(&device);
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
warn!("Cannot get device name: {}", e);
|
warn!("Cannot get device name: {e}");
|
||||||
println!(" [unknown name]");
|
println!(" [unknown name]");
|
||||||
list_formats(&device);
|
list_formats(&device);
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,7 @@ fn create_sink(
|
||||||
Some("?") => match list_outputs(host) {
|
Some("?") => match list_outputs(host) {
|
||||||
Ok(()) => exit(0),
|
Ok(()) => exit(0),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("{}", e);
|
error!("{e}");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -166,8 +166,7 @@ fn create_sink(
|
||||||
|
|
||||||
pub fn open(host: cpal::Host, device: Option<String>, format: AudioFormat) -> RodioSink {
|
pub fn open(host: cpal::Host, device: Option<String>, format: AudioFormat) -> RodioSink {
|
||||||
info!(
|
info!(
|
||||||
"Using Rodio sink with format {:?} and cpal host: {}",
|
"Using Rodio sink with format {format:?} and cpal host: {}",
|
||||||
format,
|
|
||||||
host.id().name()
|
host.id().name()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ impl Open for SdlSink {
|
||||||
AudioFormat::S32 => open_sink!(Self::S32, i32),
|
AudioFormat::S32 => open_sink!(Self::S32, i32),
|
||||||
AudioFormat::S16 => open_sink!(Self::S16, i16),
|
AudioFormat::S16 => open_sink!(Self::S16, i16),
|
||||||
_ => {
|
_ => {
|
||||||
unimplemented!("SDL currently does not support {:?} output", format)
|
unimplemented!("SDL currently does not support {format:?} output")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,8 +49,7 @@ impl<R: Read + Seek> PassthroughDecoder<R> {
|
||||||
pub fn new(rdr: R, format: AudioFileFormat) -> DecoderResult<Self> {
|
pub fn new(rdr: R, format: AudioFileFormat) -> DecoderResult<Self> {
|
||||||
if !AudioFiles::is_ogg_vorbis(format) {
|
if !AudioFiles::is_ogg_vorbis(format) {
|
||||||
return Err(DecoderError::PassthroughDecoder(format!(
|
return Err(DecoderError::PassthroughDecoder(format!(
|
||||||
"Passthrough decoder is not implemented for format {:?}",
|
"Passthrough decoder is not implemented for format {format:?}"
|
||||||
format
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +59,7 @@ impl<R: Read + Seek> PassthroughDecoder<R> {
|
||||||
.map_err(|e| DecoderError::PassthroughDecoder(e.to_string()))?;
|
.map_err(|e| DecoderError::PassthroughDecoder(e.to_string()))?;
|
||||||
let stream_serial = since_epoch.as_millis() as u32;
|
let stream_serial = since_epoch.as_millis() as u32;
|
||||||
|
|
||||||
info!("Starting passthrough track with serial {}", stream_serial);
|
info!("Starting passthrough track with serial {stream_serial}");
|
||||||
|
|
||||||
// search for ident, comment, setup
|
// search for ident, comment, setup
|
||||||
let ident = get_header(1, &mut rdr)?;
|
let ident = get_header(1, &mut rdr)?;
|
||||||
|
|
|
@ -51,8 +51,7 @@ impl SymphoniaDecoder {
|
||||||
Box::new(Mp3Reader::try_new(mss, &format_opts)?)
|
Box::new(Mp3Reader::try_new(mss, &format_opts)?)
|
||||||
} else {
|
} else {
|
||||||
return Err(DecoderError::SymphoniaDecoder(format!(
|
return Err(DecoderError::SymphoniaDecoder(format!(
|
||||||
"Unsupported format: {:?}",
|
"Unsupported format: {file_format:?}"
|
||||||
file_format
|
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -67,8 +66,7 @@ impl SymphoniaDecoder {
|
||||||
Box::new(Mp3Decoder::try_new(&track.codec_params, &decoder_opts)?)
|
Box::new(Mp3Decoder::try_new(&track.codec_params, &decoder_opts)?)
|
||||||
} else {
|
} else {
|
||||||
return Err(DecoderError::SymphoniaDecoder(format!(
|
return Err(DecoderError::SymphoniaDecoder(format!(
|
||||||
"Unsupported decoder: {:?}",
|
"Unsupported decoder: {file_format:?}"
|
||||||
file_format
|
|
||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,8 +75,7 @@ impl SymphoniaDecoder {
|
||||||
})?;
|
})?;
|
||||||
if rate != SAMPLE_RATE {
|
if rate != SAMPLE_RATE {
|
||||||
return Err(DecoderError::SymphoniaDecoder(format!(
|
return Err(DecoderError::SymphoniaDecoder(format!(
|
||||||
"Unsupported sample rate: {}",
|
"Unsupported sample rate: {rate}"
|
||||||
rate
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,8 +84,7 @@ impl SymphoniaDecoder {
|
||||||
})?;
|
})?;
|
||||||
if channels.count() != NUM_CHANNELS as usize {
|
if channels.count() != NUM_CHANNELS as usize {
|
||||||
return Err(DecoderError::SymphoniaDecoder(format!(
|
return Err(DecoderError::SymphoniaDecoder(format!(
|
||||||
"Unsupported number of channels: {}",
|
"Unsupported number of channels: {channels}"
|
||||||
channels
|
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,7 +211,7 @@ impl AudioDecoder for SymphoniaDecoder {
|
||||||
Err(Error::DecodeError(_)) => {
|
Err(Error::DecodeError(_)) => {
|
||||||
// The packet failed to decode due to corrupted or invalid data, get a new
|
// The packet failed to decode due to corrupted or invalid data, get a new
|
||||||
// packet and try again.
|
// packet and try again.
|
||||||
warn!("Skipping malformed audio packet at {} ms", position_ms);
|
warn!("Skipping malformed audio packet at {position_ms} ms");
|
||||||
skipped = true;
|
skipped = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
38
src/main.rs
38
src/main.rs
|
@ -46,10 +46,7 @@ fn usage(program: &str, opts: &getopts::Options) -> String {
|
||||||
let repo_home = env!("CARGO_PKG_REPOSITORY");
|
let repo_home = env!("CARGO_PKG_REPOSITORY");
|
||||||
let desc = env!("CARGO_PKG_DESCRIPTION");
|
let desc = env!("CARGO_PKG_DESCRIPTION");
|
||||||
let version = get_version_string();
|
let version = get_version_string();
|
||||||
let brief = format!(
|
let brief = format!("{version}\n\n{desc}\n\n{repo_home}\n\nUsage: {program} [<Options>]");
|
||||||
"{}\n\n{}\n\n{}\n\nUsage: {} [<Options>]",
|
|
||||||
version, desc, repo_home, program
|
|
||||||
);
|
|
||||||
opts.usage(&brief)
|
opts.usage(&brief)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,9 +84,9 @@ fn list_backends() {
|
||||||
println!("Available backends: ");
|
println!("Available backends: ");
|
||||||
for (&(name, _), idx) in BACKENDS.iter().zip(0..) {
|
for (&(name, _), idx) in BACKENDS.iter().zip(0..) {
|
||||||
if idx == 0 {
|
if idx == 0 {
|
||||||
println!("- {} (default)", name);
|
println!("- {name} (default)");
|
||||||
} else {
|
} else {
|
||||||
println!("- {}", name);
|
println!("- {name}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -593,8 +590,7 @@ fn get_setup() -> Setup {
|
||||||
Ok(valid) => Some(valid),
|
Ok(valid) => Some(valid),
|
||||||
Err(s) => {
|
Err(s) => {
|
||||||
eprintln!(
|
eprintln!(
|
||||||
"Command line argument was not valid Unicode and will not be evaluated: {:?}",
|
"Command line argument was not valid Unicode and will not be evaluated: {s:?}"
|
||||||
s
|
|
||||||
);
|
);
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -604,7 +600,7 @@ fn get_setup() -> Setup {
|
||||||
let matches = match opts.parse(&args[1..]) {
|
let matches = match opts.parse(&args[1..]) {
|
||||||
Ok(m) => m,
|
Ok(m) => m,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
eprintln!("Error parsing command line options: {}", e);
|
eprintln!("Error parsing command line options: {e}");
|
||||||
println!("\n{}", usage(&args[0], &opts));
|
println!("\n{}", usage(&args[0], &opts));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
@ -624,7 +620,7 @@ fn get_setup() -> Setup {
|
||||||
match v.into_string() {
|
match v.into_string() {
|
||||||
Ok(value) => Some((key, value)),
|
Ok(value) => Some((key, value)),
|
||||||
Err(s) => {
|
Err(s) => {
|
||||||
eprintln!("Environment variable was not valid Unicode and will not be evaluated: {}={:?}", key, s);
|
eprintln!("Environment variable was not valid Unicode and will not be evaluated: {key}={s:?}");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -669,11 +665,11 @@ fn get_setup() -> Setup {
|
||||||
|
|
||||||
for (k, v) in &env_vars {
|
for (k, v) in &env_vars {
|
||||||
if matches!(k.as_str(), "LIBRESPOT_PASSWORD" | "LIBRESPOT_USERNAME") {
|
if matches!(k.as_str(), "LIBRESPOT_PASSWORD" | "LIBRESPOT_USERNAME") {
|
||||||
trace!("\t\t{}=\"XXXXXXXX\"", k);
|
trace!("\t\t{k}=\"XXXXXXXX\"");
|
||||||
} else if v.is_empty() {
|
} else if v.is_empty() {
|
||||||
trace!("\t\t{}=", k);
|
trace!("\t\t{k}=");
|
||||||
} else {
|
} else {
|
||||||
trace!("\t\t{}=\"{}\"", k, v);
|
trace!("\t\t{k}=\"{v}\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -702,13 +698,13 @@ fn get_setup() -> Setup {
|
||||||
{
|
{
|
||||||
if matches!(opt, PASSWORD | PASSWORD_SHORT | USERNAME | USERNAME_SHORT) {
|
if matches!(opt, PASSWORD | PASSWORD_SHORT | USERNAME | USERNAME_SHORT) {
|
||||||
// Don't log creds.
|
// Don't log creds.
|
||||||
trace!("\t\t{} \"XXXXXXXX\"", opt);
|
trace!("\t\t{opt} \"XXXXXXXX\"");
|
||||||
} else {
|
} else {
|
||||||
let value = matches.opt_str(opt).unwrap_or_default();
|
let value = matches.opt_str(opt).unwrap_or_default();
|
||||||
if value.is_empty() {
|
if value.is_empty() {
|
||||||
trace!("\t\t{}", opt);
|
trace!("\t\t{opt}");
|
||||||
} else {
|
} else {
|
||||||
trace!("\t\t{} \"{}\"", opt, value);
|
trace!("\t\t{opt} \"{value}\"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -736,19 +732,19 @@ fn get_setup() -> Setup {
|
||||||
|
|
||||||
let invalid_error_msg =
|
let invalid_error_msg =
|
||||||
|long: &str, short: &str, invalid: &str, valid_values: &str, default_value: &str| {
|
|long: &str, short: &str, invalid: &str, valid_values: &str, default_value: &str| {
|
||||||
error!("Invalid `--{}` / `-{}`: \"{}\"", long, short, invalid);
|
error!("Invalid `--{long}` / `-{short}`: \"{invalid}\"");
|
||||||
|
|
||||||
if !valid_values.is_empty() {
|
if !valid_values.is_empty() {
|
||||||
println!("Valid `--{}` / `-{}` values: {}", long, short, valid_values);
|
println!("Valid `--{long}` / `-{short}` values: {valid_values}");
|
||||||
}
|
}
|
||||||
|
|
||||||
if !default_value.is_empty() {
|
if !default_value.is_empty() {
|
||||||
println!("Default: {}", default_value);
|
println!("Default: {default_value}");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let empty_string_error_msg = |long: &str, short: &str| {
|
let empty_string_error_msg = |long: &str, short: &str| {
|
||||||
error!("`--{}` / `-{}` can not be an empty string", long, short);
|
error!("`--{long}` / `-{short}` can not be an empty string");
|
||||||
exit(1);
|
exit(1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1095,7 +1091,7 @@ fn get_setup() -> Setup {
|
||||||
match cached_creds {
|
match cached_creds {
|
||||||
Some(creds) if username == creds.username => Some(creds),
|
Some(creds) if username == creds.username => Some(creds),
|
||||||
_ => {
|
_ => {
|
||||||
let prompt = &format!("Password for {}: ", username);
|
let prompt = &format!("Password for {username}: ");
|
||||||
match rpassword::prompt_password(prompt) {
|
match rpassword::prompt_password(prompt) {
|
||||||
Ok(password) => {
|
Ok(password) => {
|
||||||
if !password.is_empty() {
|
if !password.is_empty() {
|
||||||
|
|
Loading…
Reference in a new issue