1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! # CLASP Client Library
//!
//! High-level async client for the CLASP (Creative Low-Latency Application Streaming Protocol).
//!
//! This crate provides a Rust client for connecting to CLASP routers, enabling real-time
//! communication between creative applications such as lighting controllers, audio mixers,
//! VJ software, and more.
//!
//! ## Features
//!
//! - **Async/await**: Built on Tokio for efficient async I/O
//! - **Builder pattern**: Flexible client configuration
//! - **Subscriptions**: Pattern-based subscriptions with callbacks
//! - **Parameters**: Get/set persistent values with caching
//! - **Events**: Fire-and-forget event emission
//! - **Streams**: High-rate data streaming (QoS fire)
//! - **Bundles**: Atomic multi-message operations
//! - **Time sync**: Automatic clock synchronization with server
//!
//! ## Quick Start
//!
//! ```ignore
//! use clasp_client::Clasp;
//!
//! #[tokio::main]
//! async fn main() -> anyhow::Result<()> {
//! // Connect using builder pattern
//! let client = Clasp::builder("ws://localhost:7330")
//! .name("my-app")
//! .features(vec!["param", "event", "stream"])
//! .connect()
//! .await?;
//!
//! println!("Connected! Session: {:?}", client.session_id());
//!
//! // Subscribe to changes with wildcard patterns
//! client.subscribe("/lumen/scene/*/layer/*/opacity", |value, address| {
//! println!("{} = {:?}", address, value);
//! }).await?;
//!
//! // Set a parameter value
//! client.set("/lumen/scene/0/layer/0/opacity", 0.75).await?;
//!
//! // Emit an event (with map value)
//! client.emit("/cue/trigger", clasp_core::Value::Map(Default::default())).await?;
//!
//! // Stream high-rate data
//! for i in 0..100 {
//! let value = (i as f64 / 100.0).sin();
//! client.stream("/sensor/value", value).await?;
//! tokio::time::sleep(std::time::Duration::from_millis(10)).await;
//! }
//!
//! Ok(())
//! }
//! ```
//!
//! ## Address Patterns
//!
//! CLASP uses hierarchical addresses similar to OSC:
//!
//! - `/namespace/category/instance/property`
//! - `/lumen/scene/0/layer/3/opacity`
//! - `/midi/launchpad/cc/74`
//!
//! Wildcard patterns for subscriptions:
//!
//! - `*` - matches exactly one segment: `/path/*/value` matches `/path/foo/value`
//! - `**` - matches any number of segments: `/path/**` matches `/path/a/b/c`
//!
//! ## Signal Types
//!
//! | Type | Use Case | Persistence | QoS |
//! |------|----------|-------------|-----|
//! | `set()` | Parameters with state | Persisted | Confirm |
//! | `emit()` | One-shot events | Not persisted | Confirm |
//! | `stream()` | High-rate sensor data | Not persisted | Fire |
//! | `gesture()` | Touch/pen/motion input | Phase only | Fire |
//!
//! ## Error Handling
//!
//! All async methods return `Result<T, ClientError>`. Common errors:
//!
//! - `ClientError::NotConnected` - Operation requires active connection
//! - `ClientError::SendFailed` - Message could not be sent
//! - `ClientError::Timeout` - Operation timed out
//!
//! ## Crate Features
//!
//! - `p2p` - Enable peer-to-peer mesh networking support
pub use ClaspBuilder;
pub use Clasp;
pub use ;
pub use ;
// Re-export P2P routing mode for convenience
pub use RoutingMode;
/// Prelude for convenient imports
// Re-export types for convenience
pub use ;