<!-- Source: https://medius.k4tech.net/library/options -->
# Options

_Persistent box settings_

Options are persistent box settings, each one set and read on its own. There are four: imperfect clones, movement riding, emit-rate pacing, and the box name. All persist in NVS and survive a reboot. See the native [`OPTION`](/native/commands/option.md) command for the wire contract.

| Option | Set | Read |
| --- | --- | --- |
| imperfect clone | [`allow_imperfect_clones`](/library/options.md#allow-imperfect-clones) | [`query_imperfect`](/library/options.md#query-imperfect) |
| movement riding | [`set_movement_riding`](/library/options.md#set-movement-riding) | [`query_movement_riding`](/library/options.md#query-movement-riding) |
| emit-rate pacing | [`set_emit_pace`](/library/options.md#set-emit-pace) | [`query_emit_pace`](/library/options.md#query-emit-pace) |
| box name | [`set_name`](/library/options.md#set-name) / [`clear_name`](/library/options.md#clear-name) | [`Version::name`](/library/types/structs.md#version) |

## allow_imperfect_clones

_Clone an over-capacity device anyway_

```text
fn allow_imperfect_clones(&self, allow: bool) -> Result<()>
```

_Fire-and-forget_

By default the box refuses a device it can't clone faithfully. `true` opts into cloning an over-capacity device anyway, the rest faithful and the over-capacity interface dead; `false` is faithful-only (the default). It's persisted in NVS. When the setting changes for an _attached over-capacity_ device the box reboots itself to re-clone, so it lands without unplugging anything; a normal device is unaffected (no reboot).

#### PARAMETERS

| Parameter | Type | Description |
| --- | --- | --- |
| `allow` | `bool` | Clone an over-capacity device anyway, or stay faithful-only. |

#### EXAMPLE

```rust
use medius::Device;

let device = Device::find()?;
device.allow_imperfect_clones(true)?;   // reboots + re-clones if an over-capacity device is attached
```

## set_movement_riding

_Inject motion only on a native move_

```text
fn set_movement_riding(&self, window: Option<Duration>) -> Result<()>
```

_Fire-and-forget_

`Some(window)` turns movement riding on: injected cursor and wheel motion ride a native cursor-motion report seen within `window`, the box emits no synthetic motion frame, and motion left unridden past the window is dropped rather than dumped on the next move. So injected motion's report density matches the real mouse's, erasing the density tell. `None` turns it off (the default). The window rounds to whole milliseconds, a non-zero `Some` is at least 1 ms, and it clamps to 65535 ms; persisted in NVS.

The tradeoff is deliberate: pure idle injection, moving the cursor while the user holds still, stops working while riding is on. Button, key, and media injection are unaffected.

#### PARAMETERS

| Parameter | Type | Description |
| --- | --- | --- |
| `window` | `Option<Duration>` | `Some` with the ride window, or `None` to turn it off. |

#### EXAMPLE

```rust
use std::time::Duration;
use medius::Device;

let device = Device::find()?;
device.set_movement_riding(Some(Duration::from_millis(20)))?;  // ride native moves
device.set_movement_riding(None)?;                             // back to gapless fill
```

## set_emit_pace

_Pick what paces injected motion_

```text
fn set_emit_pace(&self, pace: EmitPace) -> Result<()>
```

_Fire-and-forget_

Picks what sets the emit-rate ceiling for injected motion. [`EmitPace::Learned`](/library/types/enums.md#emit-pace) is the default: the box paces injection to the rate the real mouse actually reports at. `EmitPace::Interval` paces to the cloned mouse's declared poll rate (its`bInterval`). `EmitPace::Fixed(hz)` paces to a rate you set; the 1 ms frame clock snaps it to `1000/n` Hz and caps it at 1 kHz. It raises the ceiling only, so idle stays idle (the box still emits a frame solely when injection is pending). Persisted in NVS.

The learnt default keeps injected motion's cadence matched to the native mouse. The other modes are for a host that models its own report density and wants the box to stop re-pacing an already-shaped stream.

#### PARAMETERS

| Parameter | Type | Description |
| --- | --- | --- |
| `pace` | [`EmitPace`](/library/types/enums.md#emit-pace) | `Learned`, `Interval`, or `Fixed(hz)`. |

#### EXAMPLE

```rust
use medius::{Device, EmitPace};

let device = Device::find()?;
device.set_emit_pace(EmitPace::Fixed(1000))?;  // emit at a fixed 1 kHz
device.set_emit_pace(EmitPace::Learned)?;      // back to the learnt native pace
```

## set_name

_Give the box a human-readable name_

```text
fn set_name(&self, name: &str) -> Result<()>
```

_Fire-and-forget_

Sets the box's name, its readable partner to the [MAC](/library/discovery.md#identity). Like the other setters it sends the value and lets the box own the rules: the firmware keeps the leading printable-ASCII run capped at 32 bytes, and an empty string clears it. Unlike the other options it is read not by a query but off [`Version::name`](/library/types/structs.md#version), like the MAC.

#### PARAMETERS

| Parameter | Type | Description |
| --- | --- | --- |
| `name` | `&str` | The new name, 1 to 32 printable ASCII characters. |

#### EXAMPLE

```rust
use medius::Device;

let device = Device::find()?;
device.set_name("Loki")?;              // the box now answers to "Loki"
let name = device.query_version()?.name;  // read it back off Version
```

## clear_name

_Back to the synthesized default_

```text
fn clear_name(&self) -> Result<()>
```

_Fire-and-forget_

Clears the custom name, reverting the box to a firmware-synthesized `Medius-XXXX` default derived from its MAC.

#### EXAMPLE

```rust
use medius::Device;

let device = Device::find()?;
device.clear_name()?;                  // back to "Medius-XXXX"
```

## query_imperfect

_Read the imperfect-clone state_

```text
fn query_imperfect(&self) -> Result<ImperfectStatus>
```

_Blocks_

Returns an [`ImperfectStatus`](/library/types/structs.md#imperfect-status): the opt-in toggle, whether the attached device is over-capacity, and whether the live clone went over-capacity anyway with one interface dead.

#### EXAMPLE

```rust
use medius::Device;

let device = Device::find()?;
let status = device.query_imperfect()?;
if status.over_capacity && !status.allowed {
    // the device was refused; opt in to clone it imperfectly
    device.allow_imperfect_clones(true)?;
}
```

## query_movement_riding

_Read the ride window_

```text
fn query_movement_riding(&self) -> Result<Option<Duration>>
```

_Blocks_

Returns the current ride window as a `Duration`, or `None` when movement riding is off.

#### EXAMPLE

```rust
use medius::Device;

let device = Device::find()?;
match device.query_movement_riding()? {
    Some(window) => println!("riding, window {window:?}"),
    None => println!("off"),
}
```

## query_emit_pace

_Read the pacing mode and rate_

```text
fn query_emit_pace(&self) -> Result<EmitPaceStatus>
```

_Blocks_

Returns an [`EmitPaceStatus`](/library/types/structs.md#emit-pace-status): the selected [`EmitPace`](/library/types/enums.md#emit-pace) mode plus `resolved_hz`, the ceiling actually in effect (0 when the pace is learnt/adaptive, or no device is attached yet in `Interval` mode).

#### EXAMPLE

```rust
use medius::{Device, EmitPace};

let device = Device::find()?;
let status = device.query_emit_pace()?;
if let EmitPace::Fixed(hz) = status.mode {
    println!("fixed {hz} Hz, emitting at {} Hz", status.resolved_hz);
}
```

## On AsyncDevice

_setters fire, queries await_

[`AsyncDevice`](/library/features/async.md) keeps `allow_imperfect_clones`, `set_movement_riding`, `set_emit_pace`, `set_name`, and `clear_name` fire-and-forget (no await) and makes `query_imperfect`, `query_movement_riding`, and `query_emit_pace` futures, like the other queries.

#### EXAMPLE

```rust
use std::time::Duration;
use medius::Device;

let device = Device::find()?.into_async();
device.set_movement_riding(Some(Duration::from_millis(20)))?;  // sync, no await
let window = device.query_movement_riding().await?;            // awaits
```
