Buttplug sex toy control library
at dev 151 lines 4.4 kB view raw
1// Buttplug Rust Source Code File - See https://buttplug.io for more info. 2// 3// Copyright 2016-2024 Nonpolynomial Labs LLC. All rights reserved. 4// 5// Licensed under the BSD 3-Clause license. See LICENSE file in the project root 6// for full license information. 7 8use super::btleplug_adapter_task::{BtleplugAdapterCommand, BtleplugAdapterTask}; 9use buttplug_core::{ButtplugResultFuture, errors::ButtplugDeviceError, util::async_manager}; 10use buttplug_server::device::hardware::communication::{ 11 HardwareCommunicationManager, 12 HardwareCommunicationManagerBuilder, 13 HardwareCommunicationManagerEvent, 14}; 15use futures::future::FutureExt; 16use std::sync::{ 17 Arc, 18 atomic::{AtomicBool, Ordering}, 19}; 20use tokio::sync::mpsc::{Sender, channel}; 21 22#[derive(Default, Clone)] 23pub struct BtlePlugCommunicationManagerBuilder { 24 require_keepalive: bool, 25} 26 27impl BtlePlugCommunicationManagerBuilder { 28 pub fn requires_keepalive(&mut self, require: bool) -> &mut Self { 29 self.require_keepalive = require; 30 self 31 } 32} 33 34impl HardwareCommunicationManagerBuilder for BtlePlugCommunicationManagerBuilder { 35 fn finish( 36 &mut self, 37 sender: Sender<HardwareCommunicationManagerEvent>, 38 ) -> Box<dyn HardwareCommunicationManager> { 39 Box::new(BtlePlugCommunicationManager::new( 40 sender, 41 self.require_keepalive, 42 )) 43 } 44} 45 46pub struct BtlePlugCommunicationManager { 47 adapter_event_sender: Sender<BtleplugAdapterCommand>, 48 scanning_status: Arc<AtomicBool>, 49 adapter_connected: Arc<AtomicBool>, 50} 51 52impl BtlePlugCommunicationManager { 53 pub fn new( 54 event_sender: Sender<HardwareCommunicationManagerEvent>, 55 require_keepalive: bool, 56 ) -> Self { 57 let (sender, receiver) = channel(256); 58 let adapter_connected = Arc::new(AtomicBool::new(false)); 59 let adapter_connected_clone = adapter_connected.clone(); 60 async_manager::spawn(async move { 61 let mut task = BtleplugAdapterTask::new( 62 event_sender, 63 receiver, 64 adapter_connected_clone, 65 require_keepalive, 66 ); 67 task.run().await; 68 }); 69 Self { 70 adapter_event_sender: sender, 71 scanning_status: Arc::new(AtomicBool::new(false)), 72 adapter_connected, 73 } 74 } 75} 76 77impl HardwareCommunicationManager for BtlePlugCommunicationManager { 78 fn name(&self) -> &'static str { 79 "BtlePlugCommunicationManager" 80 } 81 82 fn start_scanning(&mut self) -> ButtplugResultFuture { 83 let adapter_event_sender = self.adapter_event_sender.clone(); 84 let scanning_status = self.scanning_status.clone(); 85 // Set to true just to make sure we don't call ScanningFinished too early. 86 scanning_status.store(true, Ordering::Relaxed); 87 async move { 88 if adapter_event_sender 89 .send(BtleplugAdapterCommand::StartScanning) 90 .await 91 .is_err() 92 { 93 error!("Error starting scan, cannot send to btleplug event loop."); 94 scanning_status.store(false, Ordering::Relaxed); 95 Err( 96 ButtplugDeviceError::DeviceConnectionError( 97 "Cannot send start scanning request to event loop.".to_owned(), 98 ) 99 .into(), 100 ) 101 } else { 102 Ok(()) 103 } 104 } 105 .boxed() 106 } 107 108 fn stop_scanning(&mut self) -> ButtplugResultFuture { 109 let adapter_event_sender = self.adapter_event_sender.clone(); 110 // Just assume any outcome of this means we're done scanning. 111 self.scanning_status.store(false, Ordering::Relaxed); 112 async move { 113 if adapter_event_sender 114 .send(BtleplugAdapterCommand::StopScanning) 115 .await 116 .is_err() 117 { 118 error!("Error stopping scan, cannot send to btleplug event loop."); 119 Err( 120 ButtplugDeviceError::DeviceConnectionError( 121 "Cannot send stop scanning request to event loop.".to_owned(), 122 ) 123 .into(), 124 ) 125 } else { 126 Ok(()) 127 } 128 } 129 .boxed() 130 } 131 132 fn scanning_status(&self) -> bool { 133 self.scanning_status.load(Ordering::Relaxed) 134 } 135 136 fn can_scan(&self) -> bool { 137 self.adapter_connected.load(Ordering::Relaxed) 138 } 139} 140/* 141impl Drop for BtlePlugCommunicationManager { 142 fn drop(&mut self) { 143 info!("Dropping btleplug comm manager."); 144 if self.adapter.is_some() { 145 if let Err(e) = self.adapter.as_ref().expect("Already checked validity").stop_scan() { 146 info!("Error on scanning shutdown for bluetooth: {:?}", e); 147 } 148 } 149 } 150} 151 */