Autorise la configuration des noms UPNP.
This commit is contained in:
31
.claude/CLAUDE.md
Normal file
31
.claude/CLAUDE.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# PMOMusic Project Configuration
|
||||||
|
|
||||||
|
## Version Control
|
||||||
|
Ce projet utilise **Jujutsu (jj)** pour le contrôle de version, PAS git.
|
||||||
|
- Utiliser les commandes `jj` au lieu des commandes `git`
|
||||||
|
- Bookmark principal : `main`
|
||||||
|
- Ne jamais suggérer de commandes git
|
||||||
|
|
||||||
|
## Environnement
|
||||||
|
Le PATH et les variables d'environnement sont configurés dans `.claude-env` à la racine du projet.
|
||||||
|
|
||||||
|
## Configuration de l'application
|
||||||
|
- Fichier de configuration principal : `.pmomusic/config.yaml`
|
||||||
|
- Configuration UPNP personnalisable pour différencier les instances en développement
|
||||||
|
|
||||||
|
## Développement
|
||||||
|
Pendant le développement, plusieurs serveurs PMOMusic peuvent tourner en parallèle. Utiliser la configuration UPNP dans `.pmomusic/config.yaml` pour différencier les instances :
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
host:
|
||||||
|
upnp:
|
||||||
|
manufacturer: "PMOMusic-Dev1"
|
||||||
|
udn_prefix: "pmomusic-dev1"
|
||||||
|
model_name_prefix: "PMOMusic-Dev1"
|
||||||
|
friendly_name_prefix: "PMOMusic-Dev1"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
- Projet Rust multi-crates avec workspaces
|
||||||
|
- Crates principales : pmoupnp, pmomediaserver, pmomediarenderer, pmoconfig
|
||||||
|
- Pattern d'extension de configuration via traits (voir pmocache/src/config_ext.rs)
|
||||||
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -4021,6 +4021,7 @@ dependencies = [
|
|||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"serde_yaml",
|
||||||
"socket2 0.5.10",
|
"socket2 0.5.10",
|
||||||
"thiserror 2.0.17",
|
"thiserror 2.0.17",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
host:
|
host:
|
||||||
http_port: "8080"
|
http_port: "8080"
|
||||||
|
upnp:
|
||||||
|
manufacturer: "PMOMusic"
|
||||||
|
udn_prefix: "pmomusic"
|
||||||
|
model_name_prefix: "PMOMusic"
|
||||||
|
friendly_name_prefix: "PMOMusic"
|
||||||
cover_cache:
|
cover_cache:
|
||||||
directory: "cache_covers"
|
directory: "cache_covers"
|
||||||
size: 2000
|
size: 2000
|
||||||
|
|||||||
@@ -41,16 +41,13 @@ use pmoupnp::devices::Device;
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub static MEDIA_RENDERER: Lazy<Arc<Device>> = Lazy::new(|| {
|
pub static MEDIA_RENDERER: Lazy<Arc<Device>> = Lazy::new(|| {
|
||||||
let mut device = Device::new(
|
let mut device = Device::new_from_config(
|
||||||
"PMO_MediaRenderer".to_string(),
|
"PMO_MediaRenderer".to_string(),
|
||||||
"MediaRenderer".to_string(),
|
"MediaRenderer".to_string(),
|
||||||
"PMOMusic Audio Renderer".to_string(),
|
"Audio Renderer".to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
device.set_manufacturer("PMOMusic".to_string());
|
|
||||||
device.set_model_name("PMOMusic Audio Renderer".to_string());
|
|
||||||
device.set_model_description("UPnP AV MediaRenderer for audio streaming".to_string());
|
device.set_model_description("UPnP AV MediaRenderer for audio streaming".to_string());
|
||||||
device.set_udn_prefix("pmomusic".to_string());
|
|
||||||
|
|
||||||
// Ajouter les trois services obligatoires
|
// Ajouter les trois services obligatoires
|
||||||
device
|
device
|
||||||
|
|||||||
@@ -37,16 +37,13 @@ use pmoupnp::devices::Device;
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
pub static MEDIA_SERVER: Lazy<Arc<Device>> = Lazy::new(|| {
|
pub static MEDIA_SERVER: Lazy<Arc<Device>> = Lazy::new(|| {
|
||||||
let mut device = Device::new(
|
let mut device = Device::new_from_config(
|
||||||
"PMO_MediaServer".to_string(),
|
"PMO_MediaServer".to_string(),
|
||||||
"MediaServer".to_string(),
|
"MediaServer".to_string(),
|
||||||
"PMOMusic Media Server".to_string(),
|
"Media Server".to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
device.set_manufacturer("PMOMusic".to_string());
|
|
||||||
device.set_model_name("PMOMusic Media Server".to_string());
|
|
||||||
device.set_model_description("UPnP AV MediaServer for audio streaming".to_string());
|
device.set_model_description("UPnP AV MediaServer for audio streaming".to_string());
|
||||||
device.set_udn_prefix("pmomusic".to_string());
|
|
||||||
|
|
||||||
// Ajouter les deux services obligatoires
|
// Ajouter les deux services obligatoires
|
||||||
device
|
device
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ reqwest = "0.12.23"
|
|||||||
utoipa = { version = "5.3", features = ["axum_extras"] }
|
utoipa = { version = "5.3", features = ["axum_extras"] }
|
||||||
socket2 = "0.5"
|
socket2 = "0.5"
|
||||||
get_if_addrs = "0.5"
|
get_if_addrs = "0.5"
|
||||||
|
serde_yaml = "0.9"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["server"]
|
default = ["server"]
|
||||||
|
|||||||
@@ -122,6 +122,84 @@ impl Device {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Crée un nouveau modèle de device en utilisant la configuration.
|
||||||
|
///
|
||||||
|
/// Cette factory method charge les préfixes depuis pmoconfig et construit
|
||||||
|
/// automatiquement les noms finaux en combinant les préfixes avec les suffixes.
|
||||||
|
///
|
||||||
|
/// # Arguments
|
||||||
|
///
|
||||||
|
/// * `name` - Nom unique du device
|
||||||
|
/// * `device_type` - Type UPnP du device (ex: "MediaServer", "MediaRenderer")
|
||||||
|
/// * `friendly_name_suffix` - Suffixe pour le nom convivial (sera combiné avec le préfixe)
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// use pmoupnp::devices::Device;
|
||||||
|
///
|
||||||
|
/// let device = Device::new_from_config(
|
||||||
|
/// "PMO_MediaServer".to_string(),
|
||||||
|
/// "MediaServer".to_string(),
|
||||||
|
/// "Media Server".to_string(),
|
||||||
|
/// );
|
||||||
|
/// // Avec config par défaut :
|
||||||
|
/// // - manufacturer = "PMOMusic"
|
||||||
|
/// // - udn_prefix = "pmomusic"
|
||||||
|
/// // - model_name = "PMOMusic Media Server"
|
||||||
|
/// // - friendly_name = "PMOMusic Media Server"
|
||||||
|
/// ```
|
||||||
|
pub fn new_from_config(
|
||||||
|
name: String,
|
||||||
|
device_type: String,
|
||||||
|
friendly_name_suffix: String,
|
||||||
|
) -> Self {
|
||||||
|
use crate::config_ext::UpnpConfigExt;
|
||||||
|
|
||||||
|
let config = pmoconfig::get_config();
|
||||||
|
|
||||||
|
// Charger les valeurs depuis la config (avec fallback aux defaults)
|
||||||
|
let manufacturer = config
|
||||||
|
.get_upnp_manufacturer()
|
||||||
|
.unwrap_or_else(|_| "PMOMusic".to_string());
|
||||||
|
let udn_prefix = config
|
||||||
|
.get_upnp_udn_prefix()
|
||||||
|
.unwrap_or_else(|_| "pmomusic".to_string());
|
||||||
|
let model_name_prefix = config
|
||||||
|
.get_upnp_model_name_prefix()
|
||||||
|
.unwrap_or_else(|_| "PMOMusic".to_string());
|
||||||
|
let friendly_name_prefix = config
|
||||||
|
.get_upnp_friendly_name_prefix()
|
||||||
|
.unwrap_or_else(|_| "PMOMusic".to_string());
|
||||||
|
|
||||||
|
// Construire les noms finaux
|
||||||
|
let model_name = format!("{} {}", model_name_prefix, device_type);
|
||||||
|
let friendly_name = format!("{} {}", friendly_name_prefix, friendly_name_suffix);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
object: UpnpObjectType {
|
||||||
|
name: name.clone(),
|
||||||
|
object_type: "Device".to_string(),
|
||||||
|
},
|
||||||
|
device_type,
|
||||||
|
version: 1,
|
||||||
|
friendly_name,
|
||||||
|
manufacturer,
|
||||||
|
manufacturer_url: None,
|
||||||
|
model_description: None,
|
||||||
|
model_name,
|
||||||
|
model_number: None,
|
||||||
|
model_url: None,
|
||||||
|
serial_number: None,
|
||||||
|
udn_prefix,
|
||||||
|
upc: None,
|
||||||
|
icon_url: None,
|
||||||
|
presentation_url: None,
|
||||||
|
services: RwLock::new(HashMap::new()),
|
||||||
|
devices: RwLock::new(HashMap::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Retourne le type de device UPnP.
|
/// Retourne le type de device UPnP.
|
||||||
///
|
///
|
||||||
/// Format: `urn:schemas-upnp-org:device:{type}:{version}`
|
/// Format: `urn:schemas-upnp-org:device:{type}:{version}`
|
||||||
|
|||||||
@@ -261,7 +261,12 @@ impl UpnpServerExt for Server {
|
|||||||
if self.ssdp_enabled() {
|
if self.ssdp_enabled() {
|
||||||
let ssdp_opt = SSDP_SERVER.read().unwrap();
|
let ssdp_opt = SSDP_SERVER.read().unwrap();
|
||||||
if let Some(ref ssdp) = *ssdp_opt {
|
if let Some(ref ssdp) = *ssdp_opt {
|
||||||
let ssdp_device = di.to_ssdp_device("PMOMusic", "1.0");
|
use crate::config_ext::UpnpConfigExt;
|
||||||
|
let config = pmoconfig::get_config();
|
||||||
|
let manufacturer = config
|
||||||
|
.get_upnp_manufacturer()
|
||||||
|
.unwrap_or_else(|_| "PMOMusic".to_string());
|
||||||
|
let ssdp_device = di.to_ssdp_device(&manufacturer, "1.0");
|
||||||
ssdp.add_device(ssdp_device);
|
ssdp.add_device(ssdp_device);
|
||||||
info!("✅ SSDP announcement for {}", di.udn());
|
info!("✅ SSDP announcement for {}", di.udn());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user