• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use crate::btif::BluetoothInterface;
2 use crate::topstack::get_dispatchers;
3 
4 use std::sync::{Arc, Mutex};
5 use topshim_macros::cb_variant;
6 
7 #[cxx::bridge(namespace = bluetooth::topshim::rust)]
8 pub mod ffi {
9     unsafe extern "C++" {
10         include!("btav/btav_shim.h");
11 
12         type AvrcpIntf;
13 
GetAvrcpProfile(btif: *const u8) -> UniquePtr<AvrcpIntf>14         unsafe fn GetAvrcpProfile(btif: *const u8) -> UniquePtr<AvrcpIntf>;
15 
init(self: Pin<&mut AvrcpIntf>)16         fn init(self: Pin<&mut AvrcpIntf>);
cleanup(self: Pin<&mut AvrcpIntf>)17         fn cleanup(self: Pin<&mut AvrcpIntf>);
set_volume(self: Pin<&mut AvrcpIntf>, volume: i8)18         fn set_volume(self: Pin<&mut AvrcpIntf>, volume: i8);
19 
20     }
21     extern "Rust" {
avrcp_absolute_volume_enabled(enabled: bool)22         fn avrcp_absolute_volume_enabled(enabled: bool);
avrcp_absolute_volume_update(volume: i8)23         fn avrcp_absolute_volume_update(volume: i8);
24     }
25 }
26 
27 #[derive(Debug)]
28 pub enum AvrcpCallbacks {
29     AvrcpAbsoluteVolumeEnabled(bool),
30     AvrcpAbsoluteVolumeUpdate(i8),
31 }
32 
33 pub struct AvrcpCallbacksDispatcher {
34     pub dispatch: Box<dyn Fn(AvrcpCallbacks) + Send>,
35 }
36 
37 type AvrcpCb = Arc<Mutex<AvrcpCallbacksDispatcher>>;
38 
39 cb_variant!(
40     AvrcpCb,
41     avrcp_absolute_volume_enabled -> AvrcpCallbacks::AvrcpAbsoluteVolumeEnabled,
42     bool, {}
43 );
44 
45 cb_variant!(
46     AvrcpCb,
47     avrcp_absolute_volume_update -> AvrcpCallbacks::AvrcpAbsoluteVolumeUpdate,
48     i8, {}
49 );
50 
51 pub struct Avrcp {
52     internal: cxx::UniquePtr<ffi::AvrcpIntf>,
53     _is_init: bool,
54 }
55 
56 // For *const u8 opaque btif
57 unsafe impl Send for Avrcp {}
58 
59 impl Avrcp {
new(intf: &BluetoothInterface) -> Avrcp60     pub fn new(intf: &BluetoothInterface) -> Avrcp {
61         let avrcpif: cxx::UniquePtr<ffi::AvrcpIntf>;
62         unsafe {
63             avrcpif = ffi::GetAvrcpProfile(intf.as_raw_ptr());
64         }
65 
66         Avrcp { internal: avrcpif, _is_init: false }
67     }
68 
initialize(&mut self, callbacks: AvrcpCallbacksDispatcher) -> bool69     pub fn initialize(&mut self, callbacks: AvrcpCallbacksDispatcher) -> bool {
70         if get_dispatchers().lock().unwrap().set::<AvrcpCb>(Arc::new(Mutex::new(callbacks))) {
71             panic!("Tried to set dispatcher for Avrcp callbacks while it already exists");
72         }
73         self.internal.pin_mut().init();
74         true
75     }
76 
cleanup(&mut self) -> bool77     pub fn cleanup(&mut self) -> bool {
78         self.internal.pin_mut().cleanup();
79         true
80     }
81 
set_volume(&mut self, volume: i8)82     pub fn set_volume(&mut self, volume: i8) {
83         self.internal.pin_mut().set_volume(volume);
84     }
85 }
86