1use crate::{ffi, Bank, FontId, PresetId};
2use std::marker::PhantomData;
3
4pub trait IsFont {
8 fn get_id(&self) -> FontId;
9 fn get_name(&self) -> Option<&str>;
10 fn get_preset(&self, bank: Bank, num: PresetId) -> Option<PresetRef<'_>>;
11}
12
13pub trait IsPreset {
17 fn get_name(&self) -> Option<&str>;
18 fn get_banknum(&self) -> Option<Bank>;
19 fn get_num(&self) -> Option<PresetId>;
20}
21
22#[repr(transparent)]
26pub struct FontRef<'a> {
27 handle: *mut ffi::fluid_sfont_t,
28 phantom: PhantomData<&'a ()>,
29}
30
31impl<'a> FontRef<'a> {
32 pub(crate) fn from_ptr(handle: *mut ffi::fluid_sfont_t) -> Self {
33 Self {
34 handle,
35 phantom: PhantomData,
36 }
37 }
38
39 pub(crate) fn as_ptr(&self) -> *mut ffi::fluid_sfont_t {
40 self.handle
41 }
42}
43
44#[repr(transparent)]
48pub struct PresetRef<'a> {
49 handle: *mut ffi::fluid_preset_t,
50 phantom: PhantomData<&'a ()>,
51}
52
53impl<'a> PresetRef<'a> {
54 pub(crate) fn from_ptr(handle: *mut ffi::fluid_preset_t) -> Self {
55 Self {
56 handle,
57 phantom: PhantomData,
58 }
59 }
60}
61
62mod private {
63 use crate::{
64 ffi, option_from_ptr, private::HasHandle, Bank, FontId, FontRef, IsFont, IsPreset,
65 PresetId, PresetRef,
66 };
67 use std::ffi::CStr;
68
69 impl<X> IsFont for X
70 where
71 X: HasHandle<Handle = ffi::fluid_sfont_t>,
72 {
73 fn get_id(&self) -> FontId {
74 let handle = self.get_handle();
75 let font_c = unsafe { &*handle };
76 font_c.id
77 }
78
79 fn get_name(&self) -> Option<&str> {
80 let handle = self.get_handle();
81 let font_c = unsafe { &*handle };
82 let get_name = font_c.get_name?;
83 let name = unsafe { (get_name)(handle) };
84 let name = unsafe { CStr::from_ptr(name) };
85 name.to_str().ok()
86 }
87
88 fn get_preset(&self, bank: Bank, num: PresetId) -> Option<PresetRef<'_>> {
89 let handle = self.get_handle();
90 let font_c = unsafe { &*handle };
91 let get_preset = font_c.get_preset?;
92 option_from_ptr(unsafe { (get_preset)(handle, bank, num) }).map(PresetRef::from_ptr)
93 }
94 }
95
96 impl<'a> HasHandle for FontRef<'a> {
97 type Handle = ffi::fluid_sfont_t;
98
99 fn get_handle(&self) -> *mut Self::Handle {
100 self.handle
101 }
102 }
103
104 impl<X> IsPreset for X
105 where
106 X: HasHandle<Handle = ffi::fluid_preset_t>,
107 {
108 fn get_name(&self) -> Option<&str> {
109 let handle = self.get_handle();
110 let font_c = unsafe { &*handle };
111 let get_name = font_c.get_name?;
112 let name = unsafe { (get_name)(handle) };
113 let name = unsafe { CStr::from_ptr(name) };
114 name.to_str().ok()
115 }
116
117 fn get_banknum(&self) -> Option<Bank> {
118 let handle = self.get_handle();
119 let preset_c = unsafe { &*handle };
120 let get_banknum = preset_c.get_banknum?;
121 let num = unsafe { (get_banknum)(handle) };
122 if num < 0 {
123 None
124 } else {
125 Some(num as _)
126 }
127 }
128
129 fn get_num(&self) -> Option<PresetId> {
130 let handle = self.get_handle();
131 let preset_c = unsafe { &*handle };
132 let get_num = preset_c.get_num?;
133 let num = unsafe { (get_num)(handle) };
134 if num < 0 {
135 None
136 } else {
137 Some(num as _)
138 }
139 }
140 }
141
142 impl<'a> HasHandle for PresetRef<'a> {
143 type Handle = ffi::fluid_preset_t;
144
145 fn get_handle(&self) -> *mut Self::Handle {
146 self.handle
147 }
148 }
149}