pub struct StudioClient<T> { /* private fields */ }Expand description
Errors returned by high-level client operations. High-level synchronous ZMK Studio RPC client.
The generic parameter T is any transport implementing Read + Write
(for example crate::transport::serial::SerialTransport).
Implementations§
Source§impl<T: Read + Write> StudioClient<T>
impl<T: Read + Write> StudioClient<T>
Sourcepub fn new(io: T) -> Self
pub fn new(io: T) -> Self
Examples found in repository?
21fn run() -> Result<(), Box<dyn Error>> {
22 let mut args = std::env::args().skip(1);
23 let Some(mode) = args.next() else {
24 print_usage();
25 return Ok(());
26 };
27
28 match mode.as_str() {
29 "serial" => {
30 #[cfg(feature = "serial")]
31 {
32 let Some(port) = args.next() else {
33 print_usage();
34 return Ok(());
35 };
36 let client = StudioClient::new(SerialTransport::open(&port)?);
37 run_example(client)
38 }
39 #[cfg(not(feature = "serial"))]
40 {
41 Err("built without `serial` feature".into())
42 }
43 }
44 "ble" => {
45 #[cfg(feature = "ble")]
46 {
47 let devices = StudioClient::<BluestTransport>::list_ble_devices()?;
48 if devices.is_empty() {
49 return Err(
50 "No Bluetooth keyboards found. Pair/connect your keyboard first.".into(),
51 );
52 }
53 let device = &devices[0];
54 println!("Using BLE device: {}", device.display_name());
55
56 let client = StudioClient::new(BluestTransport::connect_device(&device.device_id)?);
57 run_example(client)
58 }
59 #[cfg(not(feature = "ble"))]
60 {
61 Err("built without `ble` feature".into())
62 }
63 }
64 _ => {
65 print_usage();
66 Ok(())
67 }
68 }
69}Sourcepub fn next_notification(&mut self) -> Option<Notification>
pub fn next_notification(&mut self) -> Option<Notification>
Returns the next queued notification, if any.
Sourcepub fn read_notification_blocking(
&mut self,
) -> Result<Notification, ClientError>
pub fn read_notification_blocking( &mut self, ) -> Result<Notification, ClientError>
Blocks until a notification arrives and returns it.
Sourcepub fn get_device_info(&mut self) -> Result<GetDeviceInfoResponse, ClientError>
pub fn get_device_info(&mut self) -> Result<GetDeviceInfoResponse, ClientError>
Returns static device information.
Examples found in repository?
71fn run_example<T: Read + Write>(mut client: StudioClient<T>) -> Result<(), Box<dyn Error>> {
72 let info = client.get_device_info()?;
73 println!("Device: {}", info.name);
74 println!("Lock: {:?}", client.get_lock_state()?);
75
76 let behavior_ids = client.list_all_behaviors()?;
77 println!("Behavior count: {}", behavior_ids.len());
78 if let Some(first_behavior_id) = behavior_ids.first().copied() {
79 let details = client.get_behavior_details(first_behavior_id)?;
80 println!("First behavior: {} ({})", details.id, details.display_name);
81 }
82
83 let keymap = match client.get_keymap() {
84 Ok(keymap) => keymap,
85 Err(ClientError::Meta(_)) => {
86 println!("Keymap request denied (likely locked); press `&studio_unlock` then rerun.");
87 return Ok(());
88 }
89 Err(err) => return Err(Box::new(err)),
90 };
91 println!("Layers: {}", keymap.layers.len());
92
93 let layouts = client.get_physical_layouts()?;
94 println!(
95 "Physical layouts: {} (active index: {})",
96 layouts.layouts.len(),
97 layouts.active_layout_index
98 );
99
100 let Some(first_layer) = keymap.layers.first() else {
101 return Ok(());
102 };
103 if first_layer.bindings.is_empty() {
104 return Ok(());
105 }
106
107 let layer_id = first_layer.id;
108 let key_position = 0;
109
110 let before = client.get_key_at(layer_id, key_position)?;
111 println!("Before: {before:?}");
112
113 client.set_key_at(
114 layer_id,
115 key_position,
116 Behavior::KeyPress(HidUsage::from_encoded(Keycode::A.to_hid_usage())),
117 )?;
118 let after = client.get_key_at(layer_id, key_position)?;
119 println!("After: {after:?}");
120
121 // Change management APIs.
122 let has_changes = client.check_unsaved_changes()?;
123 println!("Unsaved changes: {has_changes}");
124 if has_changes {
125 client.discard_changes()?;
126 }
127
128 Ok(())
129}Sourcepub fn get_lock_state(&mut self) -> Result<LockState, ClientError>
pub fn get_lock_state(&mut self) -> Result<LockState, ClientError>
Returns the current Studio lock state.
Examples found in repository?
71fn run_example<T: Read + Write>(mut client: StudioClient<T>) -> Result<(), Box<dyn Error>> {
72 let info = client.get_device_info()?;
73 println!("Device: {}", info.name);
74 println!("Lock: {:?}", client.get_lock_state()?);
75
76 let behavior_ids = client.list_all_behaviors()?;
77 println!("Behavior count: {}", behavior_ids.len());
78 if let Some(first_behavior_id) = behavior_ids.first().copied() {
79 let details = client.get_behavior_details(first_behavior_id)?;
80 println!("First behavior: {} ({})", details.id, details.display_name);
81 }
82
83 let keymap = match client.get_keymap() {
84 Ok(keymap) => keymap,
85 Err(ClientError::Meta(_)) => {
86 println!("Keymap request denied (likely locked); press `&studio_unlock` then rerun.");
87 return Ok(());
88 }
89 Err(err) => return Err(Box::new(err)),
90 };
91 println!("Layers: {}", keymap.layers.len());
92
93 let layouts = client.get_physical_layouts()?;
94 println!(
95 "Physical layouts: {} (active index: {})",
96 layouts.layouts.len(),
97 layouts.active_layout_index
98 );
99
100 let Some(first_layer) = keymap.layers.first() else {
101 return Ok(());
102 };
103 if first_layer.bindings.is_empty() {
104 return Ok(());
105 }
106
107 let layer_id = first_layer.id;
108 let key_position = 0;
109
110 let before = client.get_key_at(layer_id, key_position)?;
111 println!("Before: {before:?}");
112
113 client.set_key_at(
114 layer_id,
115 key_position,
116 Behavior::KeyPress(HidUsage::from_encoded(Keycode::A.to_hid_usage())),
117 )?;
118 let after = client.get_key_at(layer_id, key_position)?;
119 println!("After: {after:?}");
120
121 // Change management APIs.
122 let has_changes = client.check_unsaved_changes()?;
123 println!("Unsaved changes: {has_changes}");
124 if has_changes {
125 client.discard_changes()?;
126 }
127
128 Ok(())
129}Sourcepub fn reset_settings(&mut self) -> Result<bool, ClientError>
pub fn reset_settings(&mut self) -> Result<bool, ClientError>
Resets settings on the device.
Returns the firmware-provided success boolean.
Sourcepub fn list_all_behaviors(&mut self) -> Result<Vec<u32>, ClientError>
pub fn list_all_behaviors(&mut self) -> Result<Vec<u32>, ClientError>
Lists behavior IDs available on the connected device.
Examples found in repository?
71fn run_example<T: Read + Write>(mut client: StudioClient<T>) -> Result<(), Box<dyn Error>> {
72 let info = client.get_device_info()?;
73 println!("Device: {}", info.name);
74 println!("Lock: {:?}", client.get_lock_state()?);
75
76 let behavior_ids = client.list_all_behaviors()?;
77 println!("Behavior count: {}", behavior_ids.len());
78 if let Some(first_behavior_id) = behavior_ids.first().copied() {
79 let details = client.get_behavior_details(first_behavior_id)?;
80 println!("First behavior: {} ({})", details.id, details.display_name);
81 }
82
83 let keymap = match client.get_keymap() {
84 Ok(keymap) => keymap,
85 Err(ClientError::Meta(_)) => {
86 println!("Keymap request denied (likely locked); press `&studio_unlock` then rerun.");
87 return Ok(());
88 }
89 Err(err) => return Err(Box::new(err)),
90 };
91 println!("Layers: {}", keymap.layers.len());
92
93 let layouts = client.get_physical_layouts()?;
94 println!(
95 "Physical layouts: {} (active index: {})",
96 layouts.layouts.len(),
97 layouts.active_layout_index
98 );
99
100 let Some(first_layer) = keymap.layers.first() else {
101 return Ok(());
102 };
103 if first_layer.bindings.is_empty() {
104 return Ok(());
105 }
106
107 let layer_id = first_layer.id;
108 let key_position = 0;
109
110 let before = client.get_key_at(layer_id, key_position)?;
111 println!("Before: {before:?}");
112
113 client.set_key_at(
114 layer_id,
115 key_position,
116 Behavior::KeyPress(HidUsage::from_encoded(Keycode::A.to_hid_usage())),
117 )?;
118 let after = client.get_key_at(layer_id, key_position)?;
119 println!("After: {after:?}");
120
121 // Change management APIs.
122 let has_changes = client.check_unsaved_changes()?;
123 println!("Unsaved changes: {has_changes}");
124 if has_changes {
125 client.discard_changes()?;
126 }
127
128 Ok(())
129}Sourcepub fn get_behavior_details(
&mut self,
behavior_id: u32,
) -> Result<GetBehaviorDetailsResponse, ClientError>
pub fn get_behavior_details( &mut self, behavior_id: u32, ) -> Result<GetBehaviorDetailsResponse, ClientError>
Returns details for a behavior ID (name and parameter metadata).
Examples found in repository?
71fn run_example<T: Read + Write>(mut client: StudioClient<T>) -> Result<(), Box<dyn Error>> {
72 let info = client.get_device_info()?;
73 println!("Device: {}", info.name);
74 println!("Lock: {:?}", client.get_lock_state()?);
75
76 let behavior_ids = client.list_all_behaviors()?;
77 println!("Behavior count: {}", behavior_ids.len());
78 if let Some(first_behavior_id) = behavior_ids.first().copied() {
79 let details = client.get_behavior_details(first_behavior_id)?;
80 println!("First behavior: {} ({})", details.id, details.display_name);
81 }
82
83 let keymap = match client.get_keymap() {
84 Ok(keymap) => keymap,
85 Err(ClientError::Meta(_)) => {
86 println!("Keymap request denied (likely locked); press `&studio_unlock` then rerun.");
87 return Ok(());
88 }
89 Err(err) => return Err(Box::new(err)),
90 };
91 println!("Layers: {}", keymap.layers.len());
92
93 let layouts = client.get_physical_layouts()?;
94 println!(
95 "Physical layouts: {} (active index: {})",
96 layouts.layouts.len(),
97 layouts.active_layout_index
98 );
99
100 let Some(first_layer) = keymap.layers.first() else {
101 return Ok(());
102 };
103 if first_layer.bindings.is_empty() {
104 return Ok(());
105 }
106
107 let layer_id = first_layer.id;
108 let key_position = 0;
109
110 let before = client.get_key_at(layer_id, key_position)?;
111 println!("Before: {before:?}");
112
113 client.set_key_at(
114 layer_id,
115 key_position,
116 Behavior::KeyPress(HidUsage::from_encoded(Keycode::A.to_hid_usage())),
117 )?;
118 let after = client.get_key_at(layer_id, key_position)?;
119 println!("After: {after:?}");
120
121 // Change management APIs.
122 let has_changes = client.check_unsaved_changes()?;
123 println!("Unsaved changes: {has_changes}");
124 if has_changes {
125 client.discard_changes()?;
126 }
127
128 Ok(())
129}Sourcepub fn get_keymap(&mut self) -> Result<Keymap, ClientError>
pub fn get_keymap(&mut self) -> Result<Keymap, ClientError>
Returns the current keymap state from the device.
Examples found in repository?
71fn run_example<T: Read + Write>(mut client: StudioClient<T>) -> Result<(), Box<dyn Error>> {
72 let info = client.get_device_info()?;
73 println!("Device: {}", info.name);
74 println!("Lock: {:?}", client.get_lock_state()?);
75
76 let behavior_ids = client.list_all_behaviors()?;
77 println!("Behavior count: {}", behavior_ids.len());
78 if let Some(first_behavior_id) = behavior_ids.first().copied() {
79 let details = client.get_behavior_details(first_behavior_id)?;
80 println!("First behavior: {} ({})", details.id, details.display_name);
81 }
82
83 let keymap = match client.get_keymap() {
84 Ok(keymap) => keymap,
85 Err(ClientError::Meta(_)) => {
86 println!("Keymap request denied (likely locked); press `&studio_unlock` then rerun.");
87 return Ok(());
88 }
89 Err(err) => return Err(Box::new(err)),
90 };
91 println!("Layers: {}", keymap.layers.len());
92
93 let layouts = client.get_physical_layouts()?;
94 println!(
95 "Physical layouts: {} (active index: {})",
96 layouts.layouts.len(),
97 layouts.active_layout_index
98 );
99
100 let Some(first_layer) = keymap.layers.first() else {
101 return Ok(());
102 };
103 if first_layer.bindings.is_empty() {
104 return Ok(());
105 }
106
107 let layer_id = first_layer.id;
108 let key_position = 0;
109
110 let before = client.get_key_at(layer_id, key_position)?;
111 println!("Before: {before:?}");
112
113 client.set_key_at(
114 layer_id,
115 key_position,
116 Behavior::KeyPress(HidUsage::from_encoded(Keycode::A.to_hid_usage())),
117 )?;
118 let after = client.get_key_at(layer_id, key_position)?;
119 println!("After: {after:?}");
120
121 // Change management APIs.
122 let has_changes = client.check_unsaved_changes()?;
123 println!("Unsaved changes: {has_changes}");
124 if has_changes {
125 client.discard_changes()?;
126 }
127
128 Ok(())
129}Sourcepub fn get_physical_layouts(&mut self) -> Result<PhysicalLayouts, ClientError>
pub fn get_physical_layouts(&mut self) -> Result<PhysicalLayouts, ClientError>
Returns available physical layouts and the active layout index.
Examples found in repository?
71fn run_example<T: Read + Write>(mut client: StudioClient<T>) -> Result<(), Box<dyn Error>> {
72 let info = client.get_device_info()?;
73 println!("Device: {}", info.name);
74 println!("Lock: {:?}", client.get_lock_state()?);
75
76 let behavior_ids = client.list_all_behaviors()?;
77 println!("Behavior count: {}", behavior_ids.len());
78 if let Some(first_behavior_id) = behavior_ids.first().copied() {
79 let details = client.get_behavior_details(first_behavior_id)?;
80 println!("First behavior: {} ({})", details.id, details.display_name);
81 }
82
83 let keymap = match client.get_keymap() {
84 Ok(keymap) => keymap,
85 Err(ClientError::Meta(_)) => {
86 println!("Keymap request denied (likely locked); press `&studio_unlock` then rerun.");
87 return Ok(());
88 }
89 Err(err) => return Err(Box::new(err)),
90 };
91 println!("Layers: {}", keymap.layers.len());
92
93 let layouts = client.get_physical_layouts()?;
94 println!(
95 "Physical layouts: {} (active index: {})",
96 layouts.layouts.len(),
97 layouts.active_layout_index
98 );
99
100 let Some(first_layer) = keymap.layers.first() else {
101 return Ok(());
102 };
103 if first_layer.bindings.is_empty() {
104 return Ok(());
105 }
106
107 let layer_id = first_layer.id;
108 let key_position = 0;
109
110 let before = client.get_key_at(layer_id, key_position)?;
111 println!("Before: {before:?}");
112
113 client.set_key_at(
114 layer_id,
115 key_position,
116 Behavior::KeyPress(HidUsage::from_encoded(Keycode::A.to_hid_usage())),
117 )?;
118 let after = client.get_key_at(layer_id, key_position)?;
119 println!("After: {after:?}");
120
121 // Change management APIs.
122 let has_changes = client.check_unsaved_changes()?;
123 println!("Unsaved changes: {has_changes}");
124 if has_changes {
125 client.discard_changes()?;
126 }
127
128 Ok(())
129}Sourcepub fn set_layer_binding(
&mut self,
layer_id: u32,
key_position: i32,
binding: BehaviorBinding,
) -> Result<(), ClientError>
pub fn set_layer_binding( &mut self, layer_id: u32, key_position: i32, binding: BehaviorBinding, ) -> Result<(), ClientError>
Sets a raw behavior binding for a specific layer position.
Sourcepub fn get_key_at(
&mut self,
layer_id: u32,
key_position: i32,
) -> Result<Behavior, ClientError>
pub fn get_key_at( &mut self, layer_id: u32, key_position: i32, ) -> Result<Behavior, ClientError>
Reads a behavior from a specific layer/key position.
Examples found in repository?
71fn run_example<T: Read + Write>(mut client: StudioClient<T>) -> Result<(), Box<dyn Error>> {
72 let info = client.get_device_info()?;
73 println!("Device: {}", info.name);
74 println!("Lock: {:?}", client.get_lock_state()?);
75
76 let behavior_ids = client.list_all_behaviors()?;
77 println!("Behavior count: {}", behavior_ids.len());
78 if let Some(first_behavior_id) = behavior_ids.first().copied() {
79 let details = client.get_behavior_details(first_behavior_id)?;
80 println!("First behavior: {} ({})", details.id, details.display_name);
81 }
82
83 let keymap = match client.get_keymap() {
84 Ok(keymap) => keymap,
85 Err(ClientError::Meta(_)) => {
86 println!("Keymap request denied (likely locked); press `&studio_unlock` then rerun.");
87 return Ok(());
88 }
89 Err(err) => return Err(Box::new(err)),
90 };
91 println!("Layers: {}", keymap.layers.len());
92
93 let layouts = client.get_physical_layouts()?;
94 println!(
95 "Physical layouts: {} (active index: {})",
96 layouts.layouts.len(),
97 layouts.active_layout_index
98 );
99
100 let Some(first_layer) = keymap.layers.first() else {
101 return Ok(());
102 };
103 if first_layer.bindings.is_empty() {
104 return Ok(());
105 }
106
107 let layer_id = first_layer.id;
108 let key_position = 0;
109
110 let before = client.get_key_at(layer_id, key_position)?;
111 println!("Before: {before:?}");
112
113 client.set_key_at(
114 layer_id,
115 key_position,
116 Behavior::KeyPress(HidUsage::from_encoded(Keycode::A.to_hid_usage())),
117 )?;
118 let after = client.get_key_at(layer_id, key_position)?;
119 println!("After: {after:?}");
120
121 // Change management APIs.
122 let has_changes = client.check_unsaved_changes()?;
123 println!("Unsaved changes: {has_changes}");
124 if has_changes {
125 client.discard_changes()?;
126 }
127
128 Ok(())
129}Sourcepub fn resolve_keymap(&mut self) -> Result<Vec<Vec<Behavior>>, ClientError>
pub fn resolve_keymap(&mut self) -> Result<Vec<Vec<Behavior>>, ClientError>
Fetches the keymap and resolves every binding into a typed Behavior.
Returns a Vec of layers, each layer being a Vec<Behavior> matching
the order of bindings in the keymap. It fetches the keymap once and converts all
bindings in a single pass.
Sourcepub fn set_key_at(
&mut self,
layer_id: u32,
key_position: i32,
behavior: Behavior,
) -> Result<(), ClientError>
pub fn set_key_at( &mut self, layer_id: u32, key_position: i32, behavior: Behavior, ) -> Result<(), ClientError>
Set a behavior at a specific layer/key position.
Persist with StudioClient::save_changes or revert with StudioClient::discard_changes.
Examples found in repository?
71fn run_example<T: Read + Write>(mut client: StudioClient<T>) -> Result<(), Box<dyn Error>> {
72 let info = client.get_device_info()?;
73 println!("Device: {}", info.name);
74 println!("Lock: {:?}", client.get_lock_state()?);
75
76 let behavior_ids = client.list_all_behaviors()?;
77 println!("Behavior count: {}", behavior_ids.len());
78 if let Some(first_behavior_id) = behavior_ids.first().copied() {
79 let details = client.get_behavior_details(first_behavior_id)?;
80 println!("First behavior: {} ({})", details.id, details.display_name);
81 }
82
83 let keymap = match client.get_keymap() {
84 Ok(keymap) => keymap,
85 Err(ClientError::Meta(_)) => {
86 println!("Keymap request denied (likely locked); press `&studio_unlock` then rerun.");
87 return Ok(());
88 }
89 Err(err) => return Err(Box::new(err)),
90 };
91 println!("Layers: {}", keymap.layers.len());
92
93 let layouts = client.get_physical_layouts()?;
94 println!(
95 "Physical layouts: {} (active index: {})",
96 layouts.layouts.len(),
97 layouts.active_layout_index
98 );
99
100 let Some(first_layer) = keymap.layers.first() else {
101 return Ok(());
102 };
103 if first_layer.bindings.is_empty() {
104 return Ok(());
105 }
106
107 let layer_id = first_layer.id;
108 let key_position = 0;
109
110 let before = client.get_key_at(layer_id, key_position)?;
111 println!("Before: {before:?}");
112
113 client.set_key_at(
114 layer_id,
115 key_position,
116 Behavior::KeyPress(HidUsage::from_encoded(Keycode::A.to_hid_usage())),
117 )?;
118 let after = client.get_key_at(layer_id, key_position)?;
119 println!("After: {after:?}");
120
121 // Change management APIs.
122 let has_changes = client.check_unsaved_changes()?;
123 println!("Unsaved changes: {has_changes}");
124 if has_changes {
125 client.discard_changes()?;
126 }
127
128 Ok(())
129}Sourcepub fn check_unsaved_changes(&mut self) -> Result<bool, ClientError>
pub fn check_unsaved_changes(&mut self) -> Result<bool, ClientError>
Returns whether there are pending unsaved keymap/layout changes.
Examples found in repository?
71fn run_example<T: Read + Write>(mut client: StudioClient<T>) -> Result<(), Box<dyn Error>> {
72 let info = client.get_device_info()?;
73 println!("Device: {}", info.name);
74 println!("Lock: {:?}", client.get_lock_state()?);
75
76 let behavior_ids = client.list_all_behaviors()?;
77 println!("Behavior count: {}", behavior_ids.len());
78 if let Some(first_behavior_id) = behavior_ids.first().copied() {
79 let details = client.get_behavior_details(first_behavior_id)?;
80 println!("First behavior: {} ({})", details.id, details.display_name);
81 }
82
83 let keymap = match client.get_keymap() {
84 Ok(keymap) => keymap,
85 Err(ClientError::Meta(_)) => {
86 println!("Keymap request denied (likely locked); press `&studio_unlock` then rerun.");
87 return Ok(());
88 }
89 Err(err) => return Err(Box::new(err)),
90 };
91 println!("Layers: {}", keymap.layers.len());
92
93 let layouts = client.get_physical_layouts()?;
94 println!(
95 "Physical layouts: {} (active index: {})",
96 layouts.layouts.len(),
97 layouts.active_layout_index
98 );
99
100 let Some(first_layer) = keymap.layers.first() else {
101 return Ok(());
102 };
103 if first_layer.bindings.is_empty() {
104 return Ok(());
105 }
106
107 let layer_id = first_layer.id;
108 let key_position = 0;
109
110 let before = client.get_key_at(layer_id, key_position)?;
111 println!("Before: {before:?}");
112
113 client.set_key_at(
114 layer_id,
115 key_position,
116 Behavior::KeyPress(HidUsage::from_encoded(Keycode::A.to_hid_usage())),
117 )?;
118 let after = client.get_key_at(layer_id, key_position)?;
119 println!("After: {after:?}");
120
121 // Change management APIs.
122 let has_changes = client.check_unsaved_changes()?;
123 println!("Unsaved changes: {has_changes}");
124 if has_changes {
125 client.discard_changes()?;
126 }
127
128 Ok(())
129}Sourcepub fn save_changes(&mut self) -> Result<(), ClientError>
pub fn save_changes(&mut self) -> Result<(), ClientError>
Saves pending keymap/layout mutations made by methods like StudioClient::set_key_at.
After this succeeds, changes are persisted on the device.
Sourcepub fn discard_changes(&mut self) -> Result<bool, ClientError>
pub fn discard_changes(&mut self) -> Result<bool, ClientError>
Discards pending keymap/layout mutations made since the last save.
Returns true if there were pending changes and they were discarded.
Examples found in repository?
71fn run_example<T: Read + Write>(mut client: StudioClient<T>) -> Result<(), Box<dyn Error>> {
72 let info = client.get_device_info()?;
73 println!("Device: {}", info.name);
74 println!("Lock: {:?}", client.get_lock_state()?);
75
76 let behavior_ids = client.list_all_behaviors()?;
77 println!("Behavior count: {}", behavior_ids.len());
78 if let Some(first_behavior_id) = behavior_ids.first().copied() {
79 let details = client.get_behavior_details(first_behavior_id)?;
80 println!("First behavior: {} ({})", details.id, details.display_name);
81 }
82
83 let keymap = match client.get_keymap() {
84 Ok(keymap) => keymap,
85 Err(ClientError::Meta(_)) => {
86 println!("Keymap request denied (likely locked); press `&studio_unlock` then rerun.");
87 return Ok(());
88 }
89 Err(err) => return Err(Box::new(err)),
90 };
91 println!("Layers: {}", keymap.layers.len());
92
93 let layouts = client.get_physical_layouts()?;
94 println!(
95 "Physical layouts: {} (active index: {})",
96 layouts.layouts.len(),
97 layouts.active_layout_index
98 );
99
100 let Some(first_layer) = keymap.layers.first() else {
101 return Ok(());
102 };
103 if first_layer.bindings.is_empty() {
104 return Ok(());
105 }
106
107 let layer_id = first_layer.id;
108 let key_position = 0;
109
110 let before = client.get_key_at(layer_id, key_position)?;
111 println!("Before: {before:?}");
112
113 client.set_key_at(
114 layer_id,
115 key_position,
116 Behavior::KeyPress(HidUsage::from_encoded(Keycode::A.to_hid_usage())),
117 )?;
118 let after = client.get_key_at(layer_id, key_position)?;
119 println!("After: {after:?}");
120
121 // Change management APIs.
122 let has_changes = client.check_unsaved_changes()?;
123 println!("Unsaved changes: {has_changes}");
124 if has_changes {
125 client.discard_changes()?;
126 }
127
128 Ok(())
129}Sourcepub fn set_active_physical_layout(
&mut self,
index: u32,
) -> Result<Keymap, ClientError>
pub fn set_active_physical_layout( &mut self, index: u32, ) -> Result<Keymap, ClientError>
Sets the active physical layout by index and returns the resulting keymap.
Sourcepub fn move_layer(
&mut self,
start_index: u32,
dest_index: u32,
) -> Result<Keymap, ClientError>
pub fn move_layer( &mut self, start_index: u32, dest_index: u32, ) -> Result<Keymap, ClientError>
Moves a layer from start_index to dest_index and returns the updated keymap.
Sourcepub fn add_layer(&mut self) -> Result<AddLayerResponseDetails, ClientError>
pub fn add_layer(&mut self) -> Result<AddLayerResponseDetails, ClientError>
Adds a layer and returns firmware-provided details about the created layer.
Sourcepub fn remove_layer(&mut self, layer_index: u32) -> Result<(), ClientError>
pub fn remove_layer(&mut self, layer_index: u32) -> Result<(), ClientError>
Removes a layer by index.
Sourcepub fn restore_layer(
&mut self,
layer_id: u32,
at_index: u32,
) -> Result<Layer, ClientError>
pub fn restore_layer( &mut self, layer_id: u32, at_index: u32, ) -> Result<Layer, ClientError>
Restores a previously removed layer at a specific index.
Sourcepub fn set_layer_props(
&mut self,
layer_id: u32,
name: impl Into<String>,
) -> Result<(), ClientError>
pub fn set_layer_props( &mut self, layer_id: u32, name: impl Into<String>, ) -> Result<(), ClientError>
Sets user-facing properties for a layer (currently just name).
Source§impl StudioClient<SerialTransport>
impl StudioClient<SerialTransport>
Sourcepub fn open_serial(path: &str) -> Result<Self, SerialTransportError>
pub fn open_serial(path: &str) -> Result<Self, SerialTransportError>
Convenience constructor for opening a serial transport and wrapping it in a client.