mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-11-29 06:50:59 +00:00
03abb5c681
See discussion on #203. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs/-/merge_requests/1490>
194 lines
6.6 KiB
Rust
194 lines
6.6 KiB
Rust
// Copyright (C) 2021 Guillaume Desmottes <guillaume@desmottes.be>
|
|
//
|
|
// This Source Code Form is subject to the terms of the Mozilla Public License, v2.0.
|
|
// If a copy of the MPL was not distributed with this file, You can obtain one at
|
|
// <https://mozilla.org/MPL/2.0/>.
|
|
//
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
use anyhow::bail;
|
|
|
|
use gst::glib;
|
|
use gst::prelude::*;
|
|
|
|
use librespot::core::{
|
|
cache::Cache, config::SessionConfig, session::Session, spotify_id::SpotifyId,
|
|
};
|
|
use librespot::discovery::Credentials;
|
|
|
|
#[derive(Default, Debug, Clone)]
|
|
pub struct Settings {
|
|
username: String,
|
|
password: String,
|
|
cache_credentials: String,
|
|
cache_files: String,
|
|
cache_max_size: u64,
|
|
pub track: String,
|
|
}
|
|
|
|
impl Settings {
|
|
pub fn properties() -> Vec<glib::ParamSpec> {
|
|
vec![glib::ParamSpecString::builder("username")
|
|
.nick("Username")
|
|
.blurb("Spotify username, Facebook accounts need a device username from https://www.spotify.com/us/account/set-device-password/")
|
|
.default_value(Some(""))
|
|
.mutable_ready()
|
|
.build(),
|
|
glib::ParamSpecString::builder("password")
|
|
.nick("Password")
|
|
.blurb("Spotify password, Facebook accounts need a device password from https://www.spotify.com/us/account/set-device-password/")
|
|
.default_value(Some(""))
|
|
.mutable_ready()
|
|
.build(),
|
|
glib::ParamSpecString::builder("cache-credentials")
|
|
.nick("Credentials cache")
|
|
.blurb("Directory where to cache Spotify credentials")
|
|
.default_value(Some(""))
|
|
.mutable_ready()
|
|
.build(),
|
|
glib::ParamSpecString::builder("cache-files")
|
|
.nick("Files cache")
|
|
.blurb("Directory where to cache downloaded files from Spotify")
|
|
.default_value(Some(""))
|
|
.mutable_ready()
|
|
.build(),
|
|
glib::ParamSpecUInt64::builder("cache-max-size")
|
|
.nick("Cache max size")
|
|
.blurb("The max allowed size of the cache, in bytes, or 0 to disable the cache limit")
|
|
.default_value(0)
|
|
.mutable_ready()
|
|
.build(),
|
|
glib::ParamSpecString::builder("track")
|
|
.nick("Spotify URI")
|
|
.blurb("Spotify track URI, in the form 'spotify:track:$SPOTIFY_ID'")
|
|
.default_value(Some(""))
|
|
.mutable_ready()
|
|
.build(),
|
|
]
|
|
}
|
|
|
|
pub fn set_property(&mut self, value: &glib::Value, pspec: &glib::ParamSpec) {
|
|
match pspec.name() {
|
|
"username" => {
|
|
self.username = value.get().expect("type checked upstream");
|
|
}
|
|
"password" => {
|
|
self.password = value.get().expect("type checked upstream");
|
|
}
|
|
"cache-credentials" => {
|
|
self.cache_credentials = value.get().expect("type checked upstream");
|
|
}
|
|
"cache-files" => {
|
|
self.cache_files = value.get().expect("type checked upstream");
|
|
}
|
|
"cache-max-size" => {
|
|
self.cache_max_size = value.get().expect("type checked upstream");
|
|
}
|
|
"track" => {
|
|
self.track = value.get().expect("type checked upstream");
|
|
}
|
|
_ => unimplemented!(),
|
|
}
|
|
}
|
|
|
|
pub fn property(&self, pspec: &glib::ParamSpec) -> glib::Value {
|
|
match pspec.name() {
|
|
"username" => self.username.to_value(),
|
|
"password" => self.password.to_value(),
|
|
"cache-credentials" => self.cache_credentials.to_value(),
|
|
"cache-files" => self.cache_files.to_value(),
|
|
"cache-max-size" => self.cache_max_size.to_value(),
|
|
"track" => self.track.to_value(),
|
|
_ => unimplemented!(),
|
|
}
|
|
}
|
|
|
|
pub async fn connect_session<T>(
|
|
&self,
|
|
src: T,
|
|
cat: &gst::DebugCategory,
|
|
) -> anyhow::Result<Session>
|
|
where
|
|
T: IsA<glib::Object>,
|
|
{
|
|
let credentials_cache = if self.cache_credentials.is_empty() {
|
|
None
|
|
} else {
|
|
Some(&self.cache_credentials)
|
|
};
|
|
|
|
let files_cache = if self.cache_files.is_empty() {
|
|
None
|
|
} else {
|
|
Some(&self.cache_files)
|
|
};
|
|
|
|
let max_size = if self.cache_max_size != 0 {
|
|
Some(self.cache_max_size)
|
|
} else {
|
|
None
|
|
};
|
|
|
|
let cache = Cache::new(credentials_cache, None, files_cache, max_size)?;
|
|
|
|
if let Some(cached_cred) = cache.credentials() {
|
|
if !self.username.is_empty() && self.username != cached_cred.username {
|
|
gst::debug!(
|
|
cat,
|
|
obj: &src,
|
|
"ignore cached credentials for user {} which mismatch user {}",
|
|
cached_cred.username,
|
|
self.username
|
|
);
|
|
} else {
|
|
gst::debug!(
|
|
cat,
|
|
obj: &src,
|
|
"reuse cached credentials for user {}",
|
|
cached_cred.username
|
|
);
|
|
if let Ok((session, _credentials)) = Session::connect(
|
|
SessionConfig::default(),
|
|
cached_cred,
|
|
Some(cache.clone()),
|
|
true,
|
|
)
|
|
.await
|
|
{
|
|
return Ok(session);
|
|
}
|
|
}
|
|
}
|
|
|
|
gst::debug!(
|
|
cat,
|
|
obj: &src,
|
|
"credentials not in cache or cached credentials invalid",
|
|
);
|
|
|
|
if self.username.is_empty() {
|
|
bail!("username is not set and credentials are not in cache");
|
|
}
|
|
if self.password.is_empty() {
|
|
bail!("password is not set and credentials are not in cache");
|
|
}
|
|
|
|
let cred = Credentials::with_password(&self.username, &self.password);
|
|
|
|
let (session, _credentials) =
|
|
Session::connect(SessionConfig::default(), cred, Some(cache), true).await?;
|
|
|
|
Ok(session)
|
|
}
|
|
|
|
pub fn track_id(&self) -> anyhow::Result<SpotifyId> {
|
|
if self.track.is_empty() {
|
|
bail!("track is not set");
|
|
}
|
|
let track = SpotifyId::from_uri(&self.track).map_err(|_| {
|
|
anyhow::anyhow!("failed to create Spotify URI from track {}", self.track)
|
|
})?;
|
|
|
|
Ok(track)
|
|
}
|
|
}
|