Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,523 changes: 510 additions & 1,013 deletions Cargo.lock

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions spotify_player/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ clap = { version = "4.5.41", features = ["derive", "string"] }
config_parser2 = "0.1.6"
crossterm = "0.29.0"
dirs-next = "2.0.0"
librespot-connect = { version = "0.6.0", optional = true }
librespot-core = "0.6.0"
librespot-oauth = "0.6.0"
librespot-playback = { version = "0.6.0", optional = true }
librespot-metadata = "0.6.0"
librespot-connect = { version = "0.7.0", optional = true }
librespot-core = "0.7.0"
librespot-oauth = "0.7.0"
librespot-playback = { version = "0.7.0", optional = true }
librespot-metadata = "0.7.0"
log = "0.4.27"
chrono = "0.4.41"
reqwest = { version = "0.12.22", features = ["json"] }
Expand Down
15 changes: 9 additions & 6 deletions spotify_player/src/auth.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use crate::config;
use anyhow::Result;
use librespot_core::{authentication::Credentials, cache::Cache, config::SessionConfig, Session};
use librespot_oauth::get_access_token;

use crate::config;
use librespot_oauth::OAuthClientBuilder;

pub const SPOTIFY_CLIENT_ID: &str = "65b708073fc0480ea92a077233ca87bd";
// based on https://github.com/librespot-org/librespot/blob/f96f36c064795011f9fee912291eecb1aa46fff6/src/main.rs#L173
Expand Down Expand Up @@ -96,12 +95,16 @@ pub fn get_creds(auth_config: &AuthConfig, reauth: bool, use_cached: bool) -> Re
let msg = "No cached credentials found, please authenticate the application first.";
if reauth {
eprintln!("{msg}");
get_access_token(

let client_builder = OAuthClientBuilder::new(
SPOTIFY_CLIENT_ID,
&auth_config.login_redirect_uri,
OAUTH_SCOPES.to_vec(),
)
.map(|t| Credentials::with_access_token(t.access_token))?
);
let oauth_client = client_builder.build()?;
oauth_client
.get_access_token()
.map(|t| Credentials::with_access_token(t.access_token))?
} else {
anyhow::bail!(msg);
}
Expand Down
2 changes: 1 addition & 1 deletion spotify_player/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub struct Client {
spotify: Arc<spotify::Spotify>,
auth_config: AuthConfig,
#[cfg(feature = "streaming")]
stream_conn: Arc<Mutex<Option<librespot_connect::spirc::Spirc>>>,
stream_conn: Arc<Mutex<Option<librespot_connect::Spirc>>>,
}

impl Deref for Client {
Expand Down
2 changes: 0 additions & 2 deletions spotify_player/src/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ pub struct AppConfig {
#[cfg(feature = "media-control")]
pub enable_media_control: bool,

#[cfg(feature = "streaming")]
pub enable_streaming: StreamingType,

#[cfg(feature = "notify")]
Expand Down Expand Up @@ -323,7 +322,6 @@ impl Default for AppConfig {
#[cfg(all(unix, not(target_os = "macos")))]
enable_media_control: true,

#[cfg(feature = "streaming")]
enable_streaming: StreamingType::Always,

#[cfg(feature = "notify")]
Expand Down
2 changes: 1 addition & 1 deletion spotify_player/src/event/clipboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ pub fn get_clipboard_provider() -> Box<dyn ClipboardProvider> {
#[cfg(not(target_os = "windows"))]
{
tracing::warn!("No clipboard provider found! Fallback to a NOP clipboard provider.");
return Box::new(NopProvider {});
Box::new(NopProvider {})
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion spotify_player/src/state/ui/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ impl PageState {
}

/// The currently focused window state of the page.
pub fn focus_window_state_mut(&mut self) -> Option<MutableWindowState> {
pub fn focus_window_state_mut(&mut self) -> Option<MutableWindowState<'_>> {
match self {
Self::Library {
state:
Expand Down
11 changes: 7 additions & 4 deletions spotify_player/src/streaming.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{client::Client, config, state::SharedState};
use anyhow::Context;
use librespot_connect::{config::ConnectConfig, spirc::Spirc};
use librespot_connect::{ConnectConfig, Spirc};
use librespot_core::authentication::Credentials;
use librespot_core::Session;
use librespot_core::{config::DeviceType, spotify_id};
Expand Down Expand Up @@ -156,17 +156,20 @@ pub async fn new_connection(
let connect_config = ConnectConfig {
name: device.name.clone(),
device_type: device.device_type.parse::<DeviceType>().unwrap_or_default(),
initial_volume: Some(volume),
initial_volume: volume,

// non-configurable fields, use default values.
// We may allow users to configure these fields in a future release
has_volume_ctrl: true,
is_group: false,
disable_volume: false,
volume_steps: 64,
};

tracing::info!("Application's connect configurations: {:?}", connect_config);

let mixer = Arc::new(mixer::softmixer::SoftMixer::open(MixerConfig::default()));
let mixer = Arc::new(
mixer::softmixer::SoftMixer::open(MixerConfig::default()).context("opening softmixer")?,
);
mixer.set_volume(volume);

let backend = audio_backend::find(None).expect("should be able to find an audio backend");
Expand Down
41 changes: 7 additions & 34 deletions spotify_player/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,43 +6,16 @@ use librespot_core::session::Session;

const TIMEOUT_IN_SECS: u64 = 5;

/// The application authentication token's permission scopes
const SCOPES: [&str; 15] = [
"user-read-recently-played",
"user-top-read",
"user-read-playback-position",
"user-read-playback-state",
"user-modify-playback-state",
"user-read-currently-playing",
"streaming",
"playlist-read-private",
"playlist-modify-private",
"playlist-modify-public",
"playlist-read-collaborative",
"user-follow-read",
"user-follow-modify",
"user-library-read",
"user-library-modify",
];

pub async fn get_token_librespot(
session: &Session,
client_id: &str,
_client_id: &str,
) -> Result<librespot_core::token::Token> {
let query_uri = format!(
"hm://keymaster/token/authenticated?scope={}&client_id={}&device_id={}",
SCOPES.join(","),
client_id,
session.device_id(),
);
let request = session.mercury().get(query_uri)?;
let response = request.await?;
let data = response
.payload
.first()
.ok_or(librespot_core::token::TokenError::Empty)?
.clone();
let token = librespot_core::token::Token::from_json(String::from_utf8(data)?)?;
// TODO: figure out how to support custom client_id for Spotify Connect
let auth_data = session.auth_data();
if auth_data.is_empty() {
anyhow::bail!("Session has no stored credentials for login5 token acquisition");
}
let token = session.login5().auth_token().await.unwrap();
Ok(token)
}

Expand Down
15 changes: 6 additions & 9 deletions spotify_player/src/ui/page.rs
Original file line number Diff line number Diff line change
Expand Up @@ -276,15 +276,12 @@ pub fn render_context_page(
);

// 3+4. Construct and render the page's widgets
let id = match id {
None => {
frame.render_widget(
Paragraph::new("Cannot determine the current page's context"),
rect,
);
return;
}
Some(id) => id,
let Some(id) = id else {
frame.render_widget(
Paragraph::new("Cannot determine the current page's context"),
rect,
);
return;
};

let data = state.data.read();
Expand Down
2 changes: 1 addition & 1 deletion spotify_player/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ pub fn get_episode_show_image_url(episode: &rspotify::model::FullEpisode) -> Opt
}
}

pub fn parse_uri(uri: &str) -> Cow<str> {
pub fn parse_uri(uri: &str) -> Cow<'_, str> {
let parts = uri.split(':').collect::<Vec<_>>();
// The below URI probably has a format of `spotify:user:{user_id}:{type}:{id}`,
// but `rspotify` library expects to receive an URI of format `spotify:{type}:{id}`.
Expand Down
Loading