gilrs/ff/
server.rs

1// Copyright 2016-2018 Mateusz Sieczko and other GilRs Developers
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use super::effect_source::{DistanceModel, EffectSource, EffectState, Magnitude};
9use super::time::{Repeat, Ticks, TICK_DURATION};
10
11use std::ops::{Deref, DerefMut};
12use std::sync::mpsc::{self, Receiver, Sender};
13use std::thread;
14use std::time::{Duration, Instant};
15
16use crate::gamepad::GamepadId;
17use crate::Event;
18use gilrs_core::FfDevice;
19
20use vec_map::VecMap;
21
22#[derive(Debug)]
23pub(crate) enum Message {
24    Create {
25        id: usize,
26        effect: Box<EffectSource>,
27    },
28    HandleCloned {
29        id: usize,
30    },
31    HandleDropped {
32        id: usize,
33    },
34    Play {
35        id: usize,
36    },
37    Stop {
38        id: usize,
39    },
40    Open {
41        id: usize,
42        device: FfDevice,
43    },
44    Close {
45        id: usize,
46    },
47    SetListenerPosition {
48        id: usize,
49        position: [f32; 3],
50    },
51    SetGamepads {
52        id: usize,
53        gamepads: VecMap<()>,
54    },
55    AddGamepad {
56        id: usize,
57        gamepad_id: GamepadId,
58    },
59    SetRepeat {
60        id: usize,
61        repeat: Repeat,
62    },
63    SetDistanceModel {
64        id: usize,
65        model: DistanceModel,
66    },
67    SetPosition {
68        id: usize,
69        position: [f32; 3],
70    },
71    SetGain {
72        id: usize,
73        gain: f32,
74    },
75}
76
77pub(crate) enum FfMessage {
78    EffectCompleted { event: Event },
79}
80
81impl Message {
82    // Whether to use trace level logging or debug
83    fn use_trace_level(&self) -> bool {
84        use self::Message::*;
85
86        matches!(
87            self,
88            &SetListenerPosition { .. } | &HandleCloned { .. } | &HandleDropped { .. }
89        )
90    }
91}
92
93#[derive(Debug)]
94struct Device {
95    inner: FfDevice,
96    position: [f32; 3],
97}
98
99struct Effect {
100    source: EffectSource,
101    /// Number of created effect's handles.
102    count: usize,
103}
104
105impl Effect {
106    fn inc(&mut self) -> usize {
107        self.count += 1;
108        self.count
109    }
110
111    fn dec(&mut self) -> usize {
112        self.count -= 1;
113        self.count
114    }
115}
116
117impl From<EffectSource> for Effect {
118    fn from(source: EffectSource) -> Self {
119        Effect { source, count: 1 }
120    }
121}
122
123impl Deref for Effect {
124    type Target = EffectSource;
125
126    fn deref(&self) -> &Self::Target {
127        &self.source
128    }
129}
130
131impl DerefMut for Effect {
132    fn deref_mut(&mut self) -> &mut Self::Target {
133        &mut self.source
134    }
135}
136
137impl From<FfDevice> for Device {
138    fn from(inner: FfDevice) -> Self {
139        Device {
140            inner,
141            position: [0.0, 0.0, 0.0],
142        }
143    }
144}
145
146pub(crate) fn run(tx: Sender<FfMessage>, rx: Receiver<Message>) {
147    let mut effects = VecMap::<Effect>::new();
148    let mut devices = VecMap::<Device>::new();
149    let sleep_dur = Duration::from_millis(TICK_DURATION.into());
150    let mut tick = Ticks(0);
151    let mut completion_events = Vec::<Event>::new();
152
153    loop {
154        let t1 = Instant::now();
155        while let Ok(ev) = rx.try_recv() {
156            if ev.use_trace_level() {
157                trace!("New ff event: {:?}", ev);
158            } else {
159                debug!("New ff event: {:?}", ev);
160            }
161
162            match ev {
163                Message::Create { id, effect } => {
164                    effects.insert(id, (*effect).into());
165                }
166                Message::Play { id } => {
167                    if let Some(effect) = effects.get_mut(id) {
168                        effect.source.state = EffectState::Playing { since: tick }
169                    } else {
170                        error!("{:?} with wrong ID", ev);
171                    }
172                }
173                Message::Stop { id } => {
174                    if let Some(effect) = effects.get_mut(id) {
175                        effect.source.state = EffectState::Stopped
176                    } else {
177                        error!("{:?} with wrong ID", ev);
178                    }
179                }
180                Message::Open { id, device } => {
181                    devices.insert(id, device.into());
182                }
183                Message::Close { id } => {
184                    devices.remove(id);
185                }
186                Message::SetListenerPosition { id, position } => {
187                    if let Some(device) = devices.get_mut(id) {
188                        device.position = position;
189                    } else {
190                        error!("{:?} with wrong ID", ev);
191                    }
192                }
193                Message::HandleCloned { id } => {
194                    if let Some(effect) = effects.get_mut(id) {
195                        effect.inc();
196                    } else {
197                        error!("{:?} with wrong ID", ev);
198                    }
199                }
200                Message::HandleDropped { id } => {
201                    let mut drop = false;
202                    if let Some(effect) = effects.get_mut(id) {
203                        if effect.dec() == 0 {
204                            drop = true;
205                        }
206                    } else {
207                        error!("{:?} with wrong ID", ev);
208                    }
209
210                    if drop {
211                        effects.remove(id);
212                    }
213                }
214                Message::SetGamepads { id, gamepads } => {
215                    if let Some(eff) = effects.get_mut(id) {
216                        eff.source.devices = gamepads;
217                    } else {
218                        error!("Invalid effect id {} when changing gamepads.", id);
219                    }
220                }
221                Message::AddGamepad { id, gamepad_id } => {
222                    if let Some(eff) = effects.get_mut(id) {
223                        eff.source.devices.insert(gamepad_id.0, ());
224                    } else {
225                        error!("Invalid effect id {} when changing gamepads.", id);
226                    }
227                }
228                Message::SetRepeat { id, repeat } => {
229                    if let Some(eff) = effects.get_mut(id) {
230                        eff.source.repeat = repeat;
231                    } else {
232                        error!("Invalid effect id {} when changing repeat mode.", id);
233                    }
234                }
235                Message::SetDistanceModel { id, model } => {
236                    if let Some(eff) = effects.get_mut(id) {
237                        eff.source.distance_model = model;
238                    } else {
239                        error!("Invalid effect id {} when changing distance model.", id);
240                    }
241                }
242                Message::SetPosition { id, position } => {
243                    if let Some(eff) = effects.get_mut(id) {
244                        eff.source.position = position;
245                    } else {
246                        error!("Invalid effect id {}.", id);
247                    }
248                }
249                Message::SetGain { id, gain } => {
250                    if let Some(eff) = effects.get_mut(id) {
251                        eff.source.gain = gain;
252                    } else {
253                        error!("Invalid effect id {} when changing effect gain.", id);
254                    }
255                }
256            }
257        }
258
259        combine_and_play(&mut effects, &mut devices, tick, &mut completion_events);
260        completion_events.iter().for_each(|ev| {
261            let _ = tx.send(FfMessage::EffectCompleted { event: *ev });
262        });
263        completion_events.clear();
264
265        let dur = Instant::now().duration_since(t1);
266        if dur > sleep_dur {
267            // TODO: Should we add dur - sleep_dur to next iteration's dur?
268            warn!(
269                "One iteration of a force feedback loop took more than {}ms!",
270                TICK_DURATION
271            );
272        } else {
273            thread::sleep(sleep_dur - dur);
274        }
275        tick.inc();
276    }
277}
278
279pub(crate) fn init() -> (Sender<Message>, Receiver<FfMessage>) {
280    let (tx, _rx) = mpsc::channel();
281    let (_tx2, rx2) = mpsc::channel();
282
283    // Wasm doesn't support threads and force feedback
284    #[cfg(not(target_arch = "wasm32"))]
285    std::thread::Builder::new()
286        .name("gilrs".to_owned())
287        .spawn(move || run(_tx2, _rx))
288        .expect("failed to spawn thread");
289
290    (tx, rx2)
291}
292
293fn combine_and_play(
294    effects: &mut VecMap<Effect>,
295    devices: &mut VecMap<Device>,
296    tick: Ticks,
297    completion_events: &mut Vec<Event>,
298) {
299    for (dev_id, dev) in devices {
300        let mut magnitude = Magnitude::zero();
301        for (_, ref mut effect) in effects.iter_mut() {
302            if effect.devices.contains_key(dev_id) {
303                magnitude += effect.combine_base_effects(tick, dev.position);
304                completion_events.extend(effect.flush_completion_events());
305            }
306        }
307        trace!(
308            "({:?}) Setting ff state of {:?} to {:?}",
309            tick,
310            dev,
311            magnitude
312        );
313        dev.inner.set_ff_state(
314            magnitude.strong,
315            magnitude.weak,
316            Duration::from_millis(u64::from(TICK_DURATION) * 2),
317        );
318    }
319}