2025-10-02 18:39:32 +02:00
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
2025-11-04 22:20:35 +00:00
|
|
|
use tracing::info;
|
2025-10-03 21:19:14 +02:00
|
|
|
use xmltree::{Element, XMLNode};
|
2025-10-01 15:44:52 +02:00
|
|
|
|
2025-10-19 13:42:29 +02:00
|
|
|
use crate::actions::{Action, ActionHandler, ActionInstance, Argument, ArgumentSet};
|
|
|
|
|
use crate::{UpnpModel, UpnpObject, UpnpObjectSetError, UpnpObjectType, UpnpTyped, action_handler};
|
2025-10-01 15:44:52 +02:00
|
|
|
|
2025-10-02 18:39:32 +02:00
|
|
|
impl UpnpObject for Action {
|
2025-10-03 21:19:14 +02:00
|
|
|
fn to_xml_element(&self) -> Element {
|
2025-10-01 15:44:52 +02:00
|
|
|
let mut action_elem = Element::new("action");
|
|
|
|
|
|
|
|
|
|
// <name>
|
|
|
|
|
let mut name_elem = Element::new("name");
|
|
|
|
|
name_elem
|
|
|
|
|
.children
|
|
|
|
|
.push(XMLNode::Text(self.get_name().clone()));
|
|
|
|
|
action_elem.children.push(XMLNode::Element(name_elem));
|
|
|
|
|
|
|
|
|
|
// <argumentList>
|
2025-10-03 21:19:14 +02:00
|
|
|
let args_elem = self.arguments.to_xml_element();
|
2025-10-01 15:44:52 +02:00
|
|
|
action_elem.children.push(XMLNode::Element(args_elem));
|
|
|
|
|
|
|
|
|
|
action_elem
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-10-02 18:39:32 +02:00
|
|
|
|
|
|
|
|
impl UpnpModel for Action {
|
|
|
|
|
type Instance = ActionInstance;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl UpnpTyped for Action {
|
2025-10-01 15:44:52 +02:00
|
|
|
fn as_upnp_object_type(&self) -> &UpnpObjectType {
|
|
|
|
|
return &self.object;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Action {
|
2025-10-09 20:37:05 +02:00
|
|
|
/// Crée un handler par défaut pour une action.
|
|
|
|
|
///
|
2025-10-19 07:58:37 +02:00
|
|
|
/// Ce handler logge simplement l'appel et les arguments.
|
2025-10-09 20:37:05 +02:00
|
|
|
///
|
|
|
|
|
/// # Returns
|
|
|
|
|
///
|
2025-10-19 07:58:37 +02:00
|
|
|
/// Un [`ActionHandler`] qui logge les entrées et retourne les données telles quelles.
|
2025-10-09 20:37:05 +02:00
|
|
|
///
|
|
|
|
|
/// # Comportement
|
|
|
|
|
///
|
2025-10-19 07:58:37 +02:00
|
|
|
/// - Logge les arguments avec leurs valeurs
|
2025-10-09 20:37:05 +02:00
|
|
|
/// - Ne fait aucune modification (handler passif)
|
2025-10-19 07:58:37 +02:00
|
|
|
/// - Retourne les données telles quelles
|
2025-10-09 20:37:05 +02:00
|
|
|
///
|
|
|
|
|
/// # Note
|
|
|
|
|
///
|
|
|
|
|
/// Ce handler est automatiquement assigné lors de la création d'une action.
|
|
|
|
|
/// Il peut être remplacé via [`set_handler`](Self::set_handler).
|
|
|
|
|
fn default_handler() -> ActionHandler {
|
2025-10-19 07:58:37 +02:00
|
|
|
action_handler!(|data| {
|
2025-10-19 19:29:10 +02:00
|
|
|
let mut s = String::new();
|
2025-10-19 07:58:37 +02:00
|
|
|
// Logger les arguments
|
|
|
|
|
for (key, value) in data.iter() {
|
2025-10-19 19:29:10 +02:00
|
|
|
s.push_str(&format![
|
|
|
|
|
"- {} = {}\n",
|
2025-10-19 10:06:04 +02:00
|
|
|
key,
|
|
|
|
|
crate::actions::reflect_to_string(value.as_ref())
|
2025-10-19 19:29:10 +02:00
|
|
|
]);
|
2025-10-09 20:37:05 +02:00
|
|
|
}
|
2025-10-19 19:29:10 +02:00
|
|
|
info!("🎬 Action called with default handler\n\n{}", s);
|
2025-10-09 20:37:05 +02:00
|
|
|
|
2025-10-19 07:58:37 +02:00
|
|
|
// Retourner les données telles quelles
|
|
|
|
|
Ok(data)
|
2025-10-09 20:37:05 +02:00
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Crée une nouvelle action UPnP.
|
|
|
|
|
///
|
|
|
|
|
/// L'action est initialisée avec un handler par défaut qui logge les entrées
|
|
|
|
|
/// et retourne les valeurs des variables d'instance pour les arguments de sortie.
|
|
|
|
|
///
|
|
|
|
|
/// # Arguments
|
|
|
|
|
///
|
|
|
|
|
/// * `name` - Nom de l'action
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// # use pmoupnp::actions::Action;
|
|
|
|
|
/// let mut action = Action::new("Play".to_string());
|
|
|
|
|
/// ```
|
2025-10-01 15:44:52 +02:00
|
|
|
pub fn new(name: String) -> Action {
|
|
|
|
|
Self {
|
|
|
|
|
object: UpnpObjectType {
|
|
|
|
|
name,
|
|
|
|
|
object_type: "Action".to_string(),
|
|
|
|
|
},
|
|
|
|
|
arguments: ArgumentSet::new(),
|
2025-10-09 20:37:05 +02:00
|
|
|
handle: Self::default_handler(),
|
2025-10-19 13:42:29 +02:00
|
|
|
stateful: true, // Par défaut, les actions sont stateful
|
2025-10-01 15:44:52 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-09 20:37:05 +02:00
|
|
|
/// Ajoute un argument à l'action.
|
|
|
|
|
///
|
|
|
|
|
/// # Arguments
|
|
|
|
|
///
|
|
|
|
|
/// * `arg` - Argument à ajouter
|
|
|
|
|
///
|
|
|
|
|
/// # Errors
|
|
|
|
|
///
|
|
|
|
|
/// Retourne une erreur si un argument avec le même nom existe déjà.
|
2025-10-03 21:19:14 +02:00
|
|
|
pub fn add_argument(&mut self, arg: Arc<Argument>) -> Result<(), UpnpObjectSetError> {
|
|
|
|
|
self.arguments.insert(arg)
|
2025-10-01 15:44:52 +02:00
|
|
|
}
|
|
|
|
|
|
2025-10-09 20:37:05 +02:00
|
|
|
/// Retourne les arguments de l'action.
|
2025-10-01 15:44:52 +02:00
|
|
|
pub fn arguments(&self) -> &ArgumentSet {
|
|
|
|
|
&self.arguments
|
|
|
|
|
}
|
2025-10-09 20:37:05 +02:00
|
|
|
|
|
|
|
|
/// Définit un handler personnalisé pour cette action.
|
|
|
|
|
///
|
|
|
|
|
/// Remplace le handler par défaut par un handler personnalisé.
|
|
|
|
|
///
|
|
|
|
|
/// # Arguments
|
|
|
|
|
///
|
|
|
|
|
/// * `handler` - Le nouveau handler à utiliser
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
2025-10-09 22:36:33 +02:00
|
|
|
/// ```rust,ignore
|
|
|
|
|
/// # use pmoupnp::actions::{Action, ActionError};
|
2025-10-09 20:37:05 +02:00
|
|
|
/// # use pmoupnp::action_handler;
|
|
|
|
|
/// let mut action = Action::new("Play".to_string());
|
|
|
|
|
///
|
2025-10-19 10:06:04 +02:00
|
|
|
/// let custom_handler = action_handler!(|mut data| {
|
2025-10-09 20:37:05 +02:00
|
|
|
/// // Logique personnalisée
|
2025-10-19 10:06:04 +02:00
|
|
|
/// Ok::<_, ActionError>(data)
|
2025-10-09 20:37:05 +02:00
|
|
|
/// });
|
|
|
|
|
///
|
|
|
|
|
/// action.set_handler(custom_handler);
|
|
|
|
|
/// ```
|
|
|
|
|
pub fn set_handler(&mut self, handler: ActionHandler) {
|
|
|
|
|
self.handle = handler;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Retourne le handler de l'action.
|
|
|
|
|
pub fn handler(&self) -> &ActionHandler {
|
|
|
|
|
&self.handle
|
|
|
|
|
}
|
2025-10-19 07:58:37 +02:00
|
|
|
|
|
|
|
|
/// Définit si l'action est stateful.
|
|
|
|
|
///
|
|
|
|
|
/// Une action stateful met à jour les StateVarInstance lors de l'exécution,
|
|
|
|
|
/// déclenchant ainsi les notifications d'événements UPnP.
|
|
|
|
|
///
|
|
|
|
|
/// Une action stateless n'interagit pas avec les StateVarInstance,
|
|
|
|
|
/// ce qui améliore les performances pour les opérations purement calculatoires.
|
|
|
|
|
///
|
|
|
|
|
/// # Arguments
|
|
|
|
|
///
|
|
|
|
|
/// * `stateful` - `true` pour stateful (défaut), `false` pour stateless
|
|
|
|
|
///
|
|
|
|
|
/// # Returns
|
|
|
|
|
///
|
|
|
|
|
/// `&mut Self` pour permettre le chaînage
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// # use pmoupnp::actions::Action;
|
|
|
|
|
/// let mut action = Action::new("Calculate".to_string());
|
|
|
|
|
/// action.set_stateful(false); // Action stateless
|
|
|
|
|
/// ```
|
|
|
|
|
pub fn set_stateful(&mut self, stateful: bool) -> &mut Self {
|
|
|
|
|
self.stateful = stateful;
|
|
|
|
|
self
|
|
|
|
|
}
|
2025-10-19 13:42:29 +02:00
|
|
|
|
2025-10-19 10:06:04 +02:00
|
|
|
pub fn set_stateless(&mut self, stateless: bool) -> &mut Self {
|
|
|
|
|
self.stateful = !stateless;
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
2025-10-19 07:58:37 +02:00
|
|
|
/// Retourne `true` si l'action est stateful.
|
|
|
|
|
///
|
|
|
|
|
/// # Returns
|
|
|
|
|
///
|
|
|
|
|
/// `true` si l'action met à jour les StateVarInstance (stateful),
|
|
|
|
|
/// `false` si l'action est purement calculatoire (stateless).
|
|
|
|
|
///
|
|
|
|
|
/// # Examples
|
|
|
|
|
///
|
|
|
|
|
/// ```rust
|
|
|
|
|
/// # use pmoupnp::actions::Action;
|
|
|
|
|
/// let mut action = Action::new("Play".to_string());
|
|
|
|
|
/// assert!(action.is_stateful()); // Stateful par défaut
|
|
|
|
|
///
|
|
|
|
|
/// action.set_stateful(false);
|
|
|
|
|
/// assert!(!action.is_stateful()); // Maintenant stateless
|
|
|
|
|
/// ```
|
|
|
|
|
pub fn is_stateful(&self) -> bool {
|
|
|
|
|
self.stateful
|
|
|
|
|
}
|
2025-10-01 15:44:52 +02:00
|
|
|
}
|