mirror of
https://github.com/librespot-org/librespot.git
synced 2024-11-08 16:45:43 +00:00
Merge pull request #1302 from JoeyEamigh/add-group-flag
add flag to display connect device as group
This commit is contained in:
commit
cdff6da1f8
5 changed files with 49 additions and 1 deletions
|
@ -4,6 +4,7 @@ use crate::core::config::DeviceType;
|
||||||
pub struct ConnectConfig {
|
pub struct ConnectConfig {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub device_type: DeviceType,
|
pub device_type: DeviceType,
|
||||||
|
pub is_group: bool,
|
||||||
pub initial_volume: Option<u16>,
|
pub initial_volume: Option<u16>,
|
||||||
pub has_volume_ctrl: bool,
|
pub has_volume_ctrl: bool,
|
||||||
}
|
}
|
||||||
|
@ -13,6 +14,7 @@ impl Default for ConnectConfig {
|
||||||
ConnectConfig {
|
ConnectConfig {
|
||||||
name: "Librespot".to_string(),
|
name: "Librespot".to_string(),
|
||||||
device_type: DeviceType::default(),
|
device_type: DeviceType::default(),
|
||||||
|
is_group: false,
|
||||||
initial_volume: Some(50),
|
initial_volume: Some(50),
|
||||||
has_volume_ctrl: true,
|
has_volume_ctrl: true,
|
||||||
}
|
}
|
||||||
|
|
22
discovery/examples/discovery_group.rs
Normal file
22
discovery/examples/discovery_group.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
use futures::StreamExt;
|
||||||
|
use librespot_core::SessionConfig;
|
||||||
|
use librespot_discovery::DeviceType;
|
||||||
|
use sha1::{Digest, Sha1};
|
||||||
|
|
||||||
|
#[tokio::main(flavor = "current_thread")]
|
||||||
|
async fn main() {
|
||||||
|
let name = "Librespot Group";
|
||||||
|
let device_id = hex::encode(Sha1::digest(name.as_bytes()));
|
||||||
|
|
||||||
|
let mut server =
|
||||||
|
librespot_discovery::Discovery::builder(device_id, SessionConfig::default().client_id)
|
||||||
|
.name(name)
|
||||||
|
.device_type(DeviceType::Speaker)
|
||||||
|
.is_group(true)
|
||||||
|
.launch()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
while let Some(x) = server.next().await {
|
||||||
|
println!("Received {:?}", x);
|
||||||
|
}
|
||||||
|
}
|
|
@ -84,6 +84,7 @@ impl Builder {
|
||||||
server_config: server::Config {
|
server_config: server::Config {
|
||||||
name: "Librespot".into(),
|
name: "Librespot".into(),
|
||||||
device_type: DeviceType::default(),
|
device_type: DeviceType::default(),
|
||||||
|
is_group: false,
|
||||||
device_id: device_id.into(),
|
device_id: device_id.into(),
|
||||||
client_id: client_id.into(),
|
client_id: client_id.into(),
|
||||||
},
|
},
|
||||||
|
@ -104,6 +105,12 @@ impl Builder {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Sets whether the device is a group. This affects the icon in Spotify clients. Default is `false`.
|
||||||
|
pub fn is_group(mut self, is_group: bool) -> Self {
|
||||||
|
self.server_config.is_group = is_group;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Set the ip addresses on which it should listen to incoming connections. The default is all interfaces.
|
/// Set the ip addresses on which it should listen to incoming connections. The default is all interfaces.
|
||||||
pub fn zeroconf_ip(mut self, zeroconf_ip: Vec<std::net::IpAddr>) -> Self {
|
pub fn zeroconf_ip(mut self, zeroconf_ip: Vec<std::net::IpAddr>) -> Self {
|
||||||
self.zeroconf_ip = zeroconf_ip;
|
self.zeroconf_ip = zeroconf_ip;
|
||||||
|
|
|
@ -39,6 +39,7 @@ pub struct Config {
|
||||||
pub name: Cow<'static, str>,
|
pub name: Cow<'static, str>,
|
||||||
pub device_type: DeviceType,
|
pub device_type: DeviceType,
|
||||||
pub device_id: String,
|
pub device_id: String,
|
||||||
|
pub is_group: bool,
|
||||||
pub client_id: String,
|
pub client_id: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,6 +71,12 @@ impl RequestHandler {
|
||||||
if let Some(username) = &self.username {
|
if let Some(username) = &self.username {
|
||||||
active_user = username.to_string();
|
active_user = username.to_string();
|
||||||
}
|
}
|
||||||
|
// options based on zeroconf guide, search for `groupStatus` on page
|
||||||
|
let group_status = if self.config.is_group {
|
||||||
|
"GROUP"
|
||||||
|
} else {
|
||||||
|
"NONE"
|
||||||
|
};
|
||||||
|
|
||||||
// See: https://developer.spotify.com/documentation/commercial-hardware/implementation/guides/zeroconf/
|
// See: https://developer.spotify.com/documentation/commercial-hardware/implementation/guides/zeroconf/
|
||||||
let body = json!({
|
let body = json!({
|
||||||
|
@ -87,7 +94,8 @@ impl RequestHandler {
|
||||||
"modelDisplayName": "librespot",
|
"modelDisplayName": "librespot",
|
||||||
"libraryVersion": crate::core::version::SEMVER,
|
"libraryVersion": crate::core::version::SEMVER,
|
||||||
"resolverVersion": "1",
|
"resolverVersion": "1",
|
||||||
"groupStatus": "NONE",
|
// valid values are "GROUP" and "NONE"
|
||||||
|
"groupStatus": group_status,
|
||||||
// valid value documented & seen in the wild: "accesstoken"
|
// valid value documented & seen in the wild: "accesstoken"
|
||||||
// Using it will cause clients to fail to connect.
|
// Using it will cause clients to fail to connect.
|
||||||
"tokenType": "default",
|
"tokenType": "default",
|
||||||
|
|
|
@ -203,6 +203,7 @@ fn get_setup() -> Setup {
|
||||||
const CACHE_SIZE_LIMIT: &str = "cache-size-limit";
|
const CACHE_SIZE_LIMIT: &str = "cache-size-limit";
|
||||||
const DEVICE: &str = "device";
|
const DEVICE: &str = "device";
|
||||||
const DEVICE_TYPE: &str = "device-type";
|
const DEVICE_TYPE: &str = "device-type";
|
||||||
|
const DEVICE_IS_GROUP: &str = "group";
|
||||||
const DISABLE_AUDIO_CACHE: &str = "disable-audio-cache";
|
const DISABLE_AUDIO_CACHE: &str = "disable-audio-cache";
|
||||||
const DISABLE_CREDENTIAL_CACHE: &str = "disable-credential-cache";
|
const DISABLE_CREDENTIAL_CACHE: &str = "disable-credential-cache";
|
||||||
const DISABLE_DISCOVERY: &str = "disable-discovery";
|
const DISABLE_DISCOVERY: &str = "disable-discovery";
|
||||||
|
@ -409,6 +410,10 @@ fn get_setup() -> Setup {
|
||||||
DEVICE_TYPE,
|
DEVICE_TYPE,
|
||||||
"Displayed device type. Defaults to speaker.",
|
"Displayed device type. Defaults to speaker.",
|
||||||
"TYPE",
|
"TYPE",
|
||||||
|
).optflag(
|
||||||
|
"",
|
||||||
|
DEVICE_IS_GROUP,
|
||||||
|
"Whether the device represents a group. Defaults to false.",
|
||||||
)
|
)
|
||||||
.optopt(
|
.optopt(
|
||||||
TEMP_DIR_SHORT,
|
TEMP_DIR_SHORT,
|
||||||
|
@ -1312,11 +1317,14 @@ fn get_setup() -> Setup {
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let is_group = opt_present(DEVICE_IS_GROUP);
|
||||||
|
|
||||||
let has_volume_ctrl = !matches!(mixer_config.volume_ctrl, VolumeCtrl::Fixed);
|
let has_volume_ctrl = !matches!(mixer_config.volume_ctrl, VolumeCtrl::Fixed);
|
||||||
|
|
||||||
ConnectConfig {
|
ConnectConfig {
|
||||||
name,
|
name,
|
||||||
device_type,
|
device_type,
|
||||||
|
is_group,
|
||||||
initial_volume,
|
initial_volume,
|
||||||
has_volume_ctrl,
|
has_volume_ctrl,
|
||||||
}
|
}
|
||||||
|
@ -1685,6 +1693,7 @@ async fn main() {
|
||||||
match librespot::discovery::Discovery::builder(device_id, client_id)
|
match librespot::discovery::Discovery::builder(device_id, client_id)
|
||||||
.name(setup.connect_config.name.clone())
|
.name(setup.connect_config.name.clone())
|
||||||
.device_type(setup.connect_config.device_type)
|
.device_type(setup.connect_config.device_type)
|
||||||
|
.is_group(setup.connect_config.is_group)
|
||||||
.port(setup.zeroconf_port)
|
.port(setup.zeroconf_port)
|
||||||
.zeroconf_ip(setup.zeroconf_ip.clone())
|
.zeroconf_ip(setup.zeroconf_ip.clone())
|
||||||
.launch()
|
.launch()
|
||||||
|
|
Loading…
Reference in a new issue