Files
pmomusic/pmoupnp/src/actions/action_methods.rs

205 lines
5.9 KiB
Rust
Raw Normal View History

2025-10-02 18:39:32 +02:00
use std::sync::Arc;
use tracing::info;
2025-10-03 21:19:14 +02:00
use xmltree::{Element, XMLNode};
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-02 18:39:32 +02:00
impl UpnpObject for Action {
2025-10-03 21:19:14 +02:00
fn to_xml_element(&self) -> Element {
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();
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 {
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.
///
/// Ce handler logge simplement l'appel et les arguments.
2025-10-09 20:37:05 +02:00
///
/// # Returns
///
/// Un [`ActionHandler`] qui logge les entrées et retourne les données telles quelles.
2025-10-09 20:37:05 +02:00
///
/// # Comportement
///
/// - Logge les arguments avec leurs valeurs
2025-10-09 20:37:05 +02:00
/// - Ne fait aucune modification (handler passif)
/// - 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 {
action_handler!(|data| {
2025-10-19 19:29:10 +02:00
let mut s = String::new();
// Logger les arguments
for (key, value) in data.iter() {
2025-10-19 19:29:10 +02:00
s.push_str(&format![
"- {} = {}\n",
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
// 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());
/// ```
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-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-09 20:37:05 +02:00
/// Retourne les arguments de l'action.
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());
///
/// let custom_handler = action_handler!(|mut data| {
2025-10-09 20:37:05 +02:00
/// // Logique personnalisée
/// 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
}
/// 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
pub fn set_stateless(&mut self, stateless: bool) -> &mut Self {
self.stateful = !stateless;
self
}
/// 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
}
}