Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Adding Lovehoney Desire protocol
Fixes #56
- Loading branch information
1 parent
913d624
commit ac56b2c
Showing
3 changed files
with
176 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
use super::{ButtplugProtocol, ButtplugProtocolCreator}; | ||
use crate::{ | ||
core::{ | ||
errors::{ButtplugDeviceError, ButtplugError}, | ||
messages::{ | ||
self, ButtplugDeviceCommandMessageUnion, ButtplugMessageUnion, MessageAttributesMap, | ||
StopDeviceCmd, VibrateCmd, VibrateSubcommand, | ||
}, | ||
}, | ||
device::{ | ||
configuration_manager::DeviceProtocolConfiguration, | ||
device::{DeviceImpl, DeviceWriteCmd}, | ||
Endpoint, | ||
}, | ||
}; | ||
use async_trait::async_trait; | ||
|
||
pub struct LovehoneyDesireProtocolCreator { | ||
config: DeviceProtocolConfiguration, | ||
} | ||
|
||
impl LovehoneyDesireProtocolCreator { | ||
pub fn new(config: DeviceProtocolConfiguration) -> Self { | ||
Self { config } | ||
} | ||
} | ||
|
||
#[async_trait] | ||
impl ButtplugProtocolCreator for LovehoneyDesireProtocolCreator { | ||
async fn try_create_protocol( | ||
&self, | ||
device_impl: &Box<dyn DeviceImpl>, | ||
) -> Result<Box<dyn ButtplugProtocol>, ButtplugError> { | ||
let (names, attrs) = self.config.get_attributes(device_impl.name()).unwrap(); | ||
let name = names.get("en-us").unwrap(); | ||
Ok(Box::new(LovehoneyDesireProtocol::new(name, attrs))) | ||
} | ||
} | ||
|
||
#[derive(Clone)] | ||
pub struct LovehoneyDesireProtocol { | ||
name: String, | ||
attributes: MessageAttributesMap, | ||
sent_vibration: bool, | ||
vibrations: Vec<u8>, | ||
} | ||
|
||
impl LovehoneyDesireProtocol { | ||
pub fn new(name: &str, attributes: MessageAttributesMap) -> Self { | ||
let mut vibrations: Vec<u8> = vec![]; | ||
if let Some(attr) = attributes.get("VibrateCmd") { | ||
if let Some(count) = attr.feature_count { | ||
vibrations = vec![0; count as usize]; | ||
} | ||
} | ||
LovehoneyDesireProtocol { | ||
name: name.to_owned(), | ||
attributes, | ||
sent_vibration: false, | ||
vibrations, | ||
} | ||
} | ||
} | ||
|
||
#[async_trait] | ||
impl ButtplugProtocol for LovehoneyDesireProtocol { | ||
fn name(&self) -> &str { | ||
&self.name | ||
} | ||
|
||
fn message_attributes(&self) -> MessageAttributesMap { | ||
self.attributes.clone() | ||
} | ||
|
||
fn box_clone(&self) -> Box<dyn ButtplugProtocol> { | ||
Box::new((*self).clone()) | ||
} | ||
|
||
async fn parse_message( | ||
&mut self, | ||
device: &Box<dyn DeviceImpl>, | ||
message: &ButtplugDeviceCommandMessageUnion, | ||
) -> Result<ButtplugMessageUnion, ButtplugError> { | ||
match message { | ||
ButtplugDeviceCommandMessageUnion::StopDeviceCmd(msg) => { | ||
self.handle_stop_device_cmd(device, msg).await | ||
} | ||
ButtplugDeviceCommandMessageUnion::VibrateCmd(msg) => { | ||
self.handle_vibrate_cmd(device, msg).await | ||
} | ||
_ => Err(ButtplugError::ButtplugDeviceError( | ||
ButtplugDeviceError::new("LovehoneyDesireProtocol does not accept this message type."), | ||
)), | ||
} | ||
} | ||
} | ||
|
||
impl LovehoneyDesireProtocol { | ||
async fn handle_stop_device_cmd( | ||
&mut self, | ||
device: &Box<dyn DeviceImpl>, | ||
_: &StopDeviceCmd, | ||
) -> Result<ButtplugMessageUnion, ButtplugError> { | ||
self.handle_vibrate_cmd( | ||
device, | ||
&VibrateCmd::new( | ||
0, | ||
vec![VibrateSubcommand::new(0, 0.0); self.vibrations.len()], | ||
), | ||
) | ||
.await | ||
} | ||
|
||
async fn handle_vibrate_cmd( | ||
&mut self, | ||
device: &Box<dyn DeviceImpl>, | ||
msg: &VibrateCmd, | ||
) -> Result<ButtplugMessageUnion, ButtplugError> { | ||
let mut new_speeds = self.vibrations.clone(); | ||
let mut changed: Vec<bool> = vec![]; | ||
for _ in 0..new_speeds.len() { | ||
changed.push(!self.sent_vibration); | ||
} | ||
|
||
if new_speeds.len() == 0 || new_speeds.len() > 2 { | ||
// Should probably be an error | ||
return Ok(ButtplugMessageUnion::Ok(messages::Ok::default())); | ||
} | ||
|
||
// ToDo: Per-feature step count support? | ||
let max_value: u8 = 0x7F; | ||
|
||
for i in 0..msg.speeds.len() { | ||
//ToDo: Need safeguards | ||
let index = msg.speeds[i].index as usize; | ||
new_speeds[index] = (msg.speeds[i].speed * max_value as f64) as u8; | ||
if new_speeds[index] != self.vibrations[index] { | ||
changed[index] = true; | ||
} | ||
} | ||
|
||
self.sent_vibration = true; | ||
self.vibrations = new_speeds; | ||
|
||
if !changed.contains(&true) { | ||
return Ok(ButtplugMessageUnion::Ok(messages::Ok::default())); | ||
} | ||
|
||
// Both values are the same, something changed | ||
if self.vibrations.len() >= 2 && self.vibrations[0] == self.vibrations[1] { | ||
let msg = DeviceWriteCmd::new(Endpoint::Tx, vec![0xF3, 0, self.vibrations[0]], false); | ||
device.write_value(msg.into()).await?; | ||
return Ok(ButtplugMessageUnion::Ok(messages::Ok::default())); | ||
} | ||
|
||
if changed[0] { | ||
let msg = DeviceWriteCmd::new(Endpoint::Tx, vec![0xF3, 1, self.vibrations[0]], false); | ||
device.write_value(msg.into()).await?; | ||
} | ||
|
||
if self.vibrations.len() >= 2 && changed[1] { | ||
let msg = DeviceWriteCmd::new(Endpoint::Tx, vec![0xF3, 2, self.vibrations[1]], false); | ||
device.write_value(msg.into()).await?; | ||
} | ||
|
||
Ok(ButtplugMessageUnion::Ok(messages::Ok::default())) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters