1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use lv2_raw::LV2Feature;
use std::collections::HashMap;
use std::convert::TryFrom;
use std::ffi::{CStr, CString};
use std::sync::Mutex;
static URID_MAP: &[u8] = b"http://lv2plug.in/ns/ext/urid#map\0";
extern "C" fn do_map(handle: lv2_raw::LV2UridMapHandle, uri_ptr: *const i8) -> lv2_raw::LV2Urid {
let handle: *const Mutex<HashMap<CString, u32>> = handle as *const _;
let map_mutex = unsafe { &*handle };
let mut map = map_mutex.lock().unwrap();
let uri = unsafe { CStr::from_ptr(uri_ptr) };
if let Some(id) = map.get(uri) {
return *id;
}
let id = u32::try_from(map.len()).expect("URID space has exceeded capacity for u32.") + 1;
map.insert(uri.to_owned(), id);
id
}
extern "C" fn do_unmap(handle: lv2_sys::LV2_URID_Map_Handle, urid: lv2_raw::LV2Urid) -> *const i8 {
let handle: *const Mutex<HashMap<CString, lv2_raw::LV2Urid>> = handle as *const _;
let map_mutex = unsafe { &*handle };
let map = map_mutex.lock().unwrap();
for (uri, id) in map.iter() {
if *id == urid {
return uri.as_ptr();
}
}
std::ptr::null()
}
pub struct UridMap {
_map: Box<Mutex<HashMap<CString, u32>>>,
map_data: Box<lv2_raw::LV2UridMap>,
_unmap_data: Box<lv2_sys::LV2_URID_Unmap>,
urid_map_feature: LV2Feature,
urid_unmap_feature: LV2Feature,
}
impl UridMap {
pub fn new() -> UridMap {
let map = Box::new(Mutex::new(HashMap::new()));
let map_ptr = map.as_ref() as *const _ as *mut _;
let map_data = Box::new(lv2_raw::LV2UridMap {
handle: map_ptr,
map: do_map,
});
let map_data_ptr = map_data.as_ref() as *const _ as *mut _;
let unmap_data = Box::new(lv2_sys::LV2_URID_Unmap {
handle: map_ptr,
unmap: Some(do_unmap),
});
let unmap_data_ptr = unmap_data.as_ref() as *const _ as *mut _;
UridMap {
_map: map,
map_data,
_unmap_data: unmap_data,
urid_map_feature: LV2Feature {
uri: URID_MAP.as_ptr().cast(),
data: map_data_ptr,
},
urid_unmap_feature: LV2Feature {
uri: b"http://lv2plug.in/ns/ext/urid#unmap\0".as_ptr().cast(),
data: unmap_data_ptr,
},
}
}
pub fn map(&self, uri: &CStr) -> u32 {
do_map(self.map_data.handle, uri.as_ptr())
}
pub fn as_urid_map_feature(&self) -> &LV2Feature {
&self.urid_map_feature
}
pub fn as_urid_unmap_feature(&self) -> &LV2Feature {
&self.urid_unmap_feature
}
}