Skip to content

Commit

Permalink
fix: Correct VibrateCmd -> ScalarCmd conversion when the devices has …
Browse files Browse the repository at this point in the history
…non-vibrate features

This change reworks the conversion from VibrateCmd to ScalarCmd by building
a map of indexes of vibrate features on a devices that supports ScalarCmd
so that devices that have non-vibrators before or embedded between vibrators
don't try to send vibrate commands to the those features.

`VibrateCmd( 0, [1.0, 0.5] )` for a device with `ScalarCmd(Vibrate, Rotate, Vibrate)`
now generates `ScalarCmd( 0, [ {0, 1.0, Vibrate}, {2, 0.5, Vibrate}] )` vs previously
just copying the feature index, which would have produced the invalid:
`ScalarCmd( 0, [ {0, 1.0, Vibrate}, {1, 0.5, Vibrate}] )`
  • Loading branch information
blackspherefollower authored and qdot committed May 11, 2024
1 parent 89d14bb commit 47d8ee2
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 20 deletions.
15 changes: 0 additions & 15 deletions buttplug/src/core/message/scalar_cmd.rs
Expand Up @@ -72,18 +72,3 @@ impl ButtplugMessageValidator for ScalarCmd {
Ok(())
}
}

impl From<VibrateCmd> for ScalarCmd {
fn from(vibrate_cmd: VibrateCmd) -> Self {
let subcommands: Vec<ScalarSubcommand> = vibrate_cmd
.speeds()
.iter()
.map(|x| ScalarSubcommand::new(x.index(), x.speed(), ActuatorType::Vibrate))
.collect();
Self {
id: vibrate_cmd.id(),
device_index: vibrate_cmd.device_index(),
scalars: subcommands,
}
}
}
53 changes: 50 additions & 3 deletions buttplug/src/server/device/server_device.rs
Expand Up @@ -11,6 +11,8 @@ use std::{
time::Duration,
};

use crate::core::errors::ButtplugError::ButtplugMessageError;

Check warning on line 14 in buttplug/src/server/device/server_device.rs

View workflow job for this annotation

GitHub Actions / build-stable (ubuntu-latest)

unused import: `crate::core::errors::ButtplugError::ButtplugMessageError`

Check warning on line 14 in buttplug/src/server/device/server_device.rs

View workflow job for this annotation

GitHub Actions / build-stable (ubuntu-latest)

unused import: `crate::core::errors::ButtplugError::ButtplugMessageError`

Check warning on line 14 in buttplug/src/server/device/server_device.rs

View workflow job for this annotation

GitHub Actions / build-stable (macos-latest)

unused import: `crate::core::errors::ButtplugError::ButtplugMessageError`

Check warning on line 14 in buttplug/src/server/device/server_device.rs

View workflow job for this annotation

GitHub Actions / build-stable (macos-latest)

unused import: `crate::core::errors::ButtplugError::ButtplugMessageError`

Check warning on line 14 in buttplug/src/server/device/server_device.rs

View workflow job for this annotation

GitHub Actions / build-stable (windows-latest)

unused import: `crate::core::errors::ButtplugError::ButtplugMessageError`

Check warning on line 14 in buttplug/src/server/device/server_device.rs

View workflow job for this annotation

GitHub Actions / build-stable (windows-latest)

unused import: `crate::core::errors::ButtplugError::ButtplugMessageError`
use crate::core::message::VibrateCmd;
use crate::{
core::{
errors::{ButtplugDeviceError, ButtplugError},
Expand Down Expand Up @@ -530,9 +532,7 @@ impl ServerDevice {
};
self.handle_generic_command_result(self.handler.handle_rotate_cmd(&commands))
}
ButtplugDeviceCommandMessageUnion::VibrateCmd(msg) => {
self.parse_message(ScalarCmd::from(msg).into())
}
ButtplugDeviceCommandMessageUnion::VibrateCmd(msg) => self.handle_vibrate_cmd(msg),
ButtplugDeviceCommandMessageUnion::LinearCmd(msg) => {
self.handle_generic_command_result(self.handler.handle_linear_cmd(msg))
}
Expand Down Expand Up @@ -709,6 +709,53 @@ impl ServerDevice {
.boxed()
}

fn handle_vibrate_cmd(&self, message: VibrateCmd) -> ButtplugServerResultFuture {
if let Some(attr) = self.attributes.message_attributes().scalar_cmd() {
let mut indexes = Vec::new();
for (i, attr) in attr.iter().enumerate() {
if attr.actuator_type() == &ActuatorType::Vibrate {
indexes.push(i as u32);
}
}

let mut cmds: Vec<ScalarSubcommand> = Vec::new();
for s in message.speeds().iter() {
if s.index() >= indexes.len() as u32 {
return ButtplugDeviceError::ProtocolRequirementError(format!(
"{} has {} vibrating features; {} is out of range.",
self.name(),
indexes.len(),
s.index()
))
.into();
}
cmds.push(ScalarSubcommand::new(
indexes[s.index() as usize],
s.speed(),
ActuatorType::Vibrate,
));
}

if cmds.is_empty() {
ButtplugDeviceError::ProtocolRequirementError(format!(
"{} has no vibrating features.",
self.name()
))
.into()
} else {
let mut vibrate_cmd = ScalarCmd::new(message.device_index(), cmds);
vibrate_cmd.set_id(message.id());
self.parse_message(vibrate_cmd.into())
}
} else {
ButtplugDeviceError::ProtocolRequirementError(format!(
"{} needs to support ScalarCmd to use SingleMotorVibrateCmd.",
self.name()
))
.into()
}
}

fn handle_single_motor_vibrate_cmd(
&self,
message: message::SingleMotorVibrateCmd,
Expand Down
8 changes: 6 additions & 2 deletions buttplug/tests/test_device_protocols.rs
Expand Up @@ -97,7 +97,8 @@ async fn load_test_case(test_file: &str) -> DeviceTestCase {
#[test_case("test_longlosttouch_protocol.yaml" ; "LongLostTouch Protocol")]
#[test_case("test_adrienlastic_protocol.yaml" ; "Adrien Lastic Protocol")]
#[test_case("test_foreo_protocol.yaml" ; "Foreo Protocol")]
#[test_case("test_joyhub_protocol.yaml" ; "JoyHub Protocol")]
#[test_case("test_joyhub_petalwish.yaml" ; "JoyHub Protocol - Petalwish")]
#[test_case("test_joyhub_petalwish_compat.yaml" ; "JoyHub Protocol - Petalwish Compat")]
#[test_case("test_itoys_protocol.yaml" ; "iToys Protocol")]
#[test_case("test_leten_protocol.yaml" ; "Leten Protocol")]
#[test_case("test_motorbunny_protocol.yaml" ; "Motorbunny Protocol")]
Expand Down Expand Up @@ -187,7 +188,8 @@ async fn test_device_protocols_embedded_v3(test_file: &str) {
#[test_case("test_xiuxiuda_protocol.yaml" ; "Xiuxiuda Protocol")]
#[test_case("test_adrienlastic_protocol.yaml" ; "Adrien Lastic Protocol")]
#[test_case("test_foreo_protocol.yaml" ; "Foreo Protocol")]
#[test_case("test_joyhub_protocol.yaml" ; "JoyHub Protocol")]
#[test_case("test_joyhub_petalwish.yaml" ; "JoyHub Protocol - Petalwish")]
#[test_case("test_joyhub_petalwish_compat.yaml" ; "JoyHub Protocol - Petalwish Compat")]
#[test_case("test_itoys_protocol.yaml" ; "iToys Protocol")]
#[test_case("test_leten_protocol.yaml" ; "Leten Protocol")]
#[test_case("test_motorbunny_protocol.yaml" ; "Motorbunny Protocol")]
Expand Down Expand Up @@ -254,6 +256,7 @@ async fn test_device_protocols_json_v3(test_file: &str) {
#[test_case("test_xiuxiuda_protocol.yaml" ; "Xiuxiuda Protocol")]
#[test_case("test_adrienlastic_protocol.yaml" ; "Adrien Lastic Protocol")]
#[test_case("test_foreo_protocol.yaml" ; "Foreo Protocol")]
#[test_case("test_joyhub_petalwish_compat.yaml" ; "JoyHub Protocol - Petalwish Compat")]
#[test_case("test_itoys_protocol.yaml" ; "iToys Protocol")]
#[test_case("test_leten_protocol.yaml" ; "Leten Protocol")]
#[test_case("test_motorbunny_protocol.yaml" ; "Motorbunny Protocol")]
Expand Down Expand Up @@ -319,6 +322,7 @@ async fn test_device_protocols_embedded_v2(test_file: &str) {
#[test_case("test_xiuxiuda_protocol.yaml" ; "Xiuxiuda Protocol")]
#[test_case("test_adrienlastic_protocol.yaml" ; "Adrien Lastic Protocol")]
#[test_case("test_foreo_protocol.yaml" ; "Foreo Protocol")]
#[test_case("test_joyhub_petalwish_compat.yaml" ; "JoyHub Protocol - Petalwish Compat")]
#[test_case("test_itoys_protocol.yaml" ; "iToys Protocol")]
#[test_case("test_leten_protocol.yaml" ; "Leten Protocol")]
#[test_case("test_motorbunny_protocol.yaml" ; "Motorbunny Protocol")]
Expand Down
@@ -0,0 +1,30 @@
devices:
- identifier:
name: "J-Petalwish2"
expected_name: "JoyHub Petalwish 2"
device_commands:
# Commands
- !Messages
device_index: 0
messages:
- !Vibrate
- Index: 0
Speed: 0.5
- !Commands
device_index: 0
commands:
- !Write
endpoint: tx
data: [0xa0, 0x03, 0x00, 0x00, 0x80, 0x00, 0xaa]
write_with_response: false
- !Messages
device_index: 0
messages:
- !Stop
- !Commands
device_index: 0
commands:
- !Write
endpoint: tx
data: [0xa0, 0x03, 0x00, 0x00, 0x00, 0x00, 0xaa]
write_with_response: false

0 comments on commit 47d8ee2

Please sign in to comment.