1use libloading::Library;
2use once_cell::sync::{Lazy, OnceCell};
3
4use crate::{
5 generate_bindings,
6 types::{
7 Bass3DVector, BassChannelInfo, BassDeviceInfo, BassFileProcs, BassInfo, BassPluginInfo,
8 BassRecordInfo, BassSample, BOOL, DOWNLOADPROC, DSPPROC, DWORD, HCHANNEL, HDSP, HFX,
9 HMUSIC, HPLUGIN, HRECORD, HSAMPLE, HSTREAM, HSYNC, QWORD, RECORDPROC, STREAMPROC, SYNCPROC,
10 },
11};
12use std::{
13 env,
14 os::raw::{c_char, c_int, c_void},
15 path::PathBuf,
16};
17
18static BASS_LIBRARY_NAME: OnceCell<String> = OnceCell::new();
19static BASS_LIBRARY_SEARCH_PATHS: OnceCell<Vec<PathBuf>> = OnceCell::new();
20
21static BASS_LIBRARY: Lazy<Library> = Lazy::new(|| {
22 let library_name = BASS_LIBRARY_NAME.get_or_init(|| {
23 #[cfg(target_os = "windows")]
24 return String::from("bass.dll");
25
26 #[cfg(target_os = "linux")]
27 return String::from("libbass.so");
28
29 #[cfg(target_os = "macos")]
30 return String::from("libbass.dylib");
31 });
32
33 let library_search_paths = BASS_LIBRARY_SEARCH_PATHS.get_or_init(|| {
34 if let Ok(mut current_directory) = env::current_exe() {
35 current_directory.pop();
36
37 return vec![current_directory];
38 } else {
39 panic!("Failed to retrieve current working directory, can't initialize library search paths.");
40 }
41 });
42
43 for library_search_path in library_search_paths {
44 let library_path = library_search_path.join(library_name);
45
46 if library_path.exists() && library_path.is_file() {
47 if let Ok(library) = unsafe { Library::new(library_path) } {
48 return library;
49 } else {
50 panic!("Failed to load the library.");
51 }
52 }
53 }
54
55 panic!("Couldn't find the library.");
56});
57
58pub fn set_library_name(name: String) -> Result<(), String> {
83 BASS_LIBRARY_NAME.set(name)
84}
85
86pub fn set_library_search_paths(search_paths: Vec<PathBuf>) -> Result<(), Vec<PathBuf>> {
94 BASS_LIBRARY_SEARCH_PATHS.set(search_paths)
95}
96
97generate_bindings! {
98 binding BASS_SET_CONFIG fn BASS_SetConfig(option: DWORD, value: DWORD) -> BOOL;
99 binding BASS_GET_CONFIG fn BASS_GetConfig(option: DWORD) -> DWORD;
100 binding BASS_SET_CONFIG_PTR fn BASS_SetConfigPtr(option: DWORD, value: *mut c_void) -> BOOL;
101 binding BASS_GET_CONFIG_PTR fn BASS_GetConfigPtr(option: DWORD) -> *mut c_void;
102 binding BASS_GET_VERSION fn BASS_GetVersion() -> DWORD;
103 binding BASS_ERROR_GET_CODE fn BASS_ErrorGetCode() -> c_int;
104 binding BASS_GET_DEVICE_INFO fn BASS_GetDeviceInfo(device: DWORD, info: *mut BassDeviceInfo) -> BOOL;
105 binding BASS_INIT fn BASS_Init(
106 device: c_int,
107 frequency: DWORD,
108 flags: DWORD,
109 window: *mut c_void,
110 dsguid: *mut c_void
111 ) -> BOOL;
112 binding BASS_SET_DEVICE fn BASS_SetDevice(device: DWORD) -> BOOL;
113 binding BASS_GET_DEVICE fn BASS_GetDevice() -> DWORD;
114 binding BASS_FREE fn BASS_Free() -> BOOL;
115 binding BASS_GET_INFO fn BASS_GetInfo(info: *mut BassInfo) -> BOOL;
116 binding BASS_UPDATE fn BASS_Update(length: DWORD) -> BOOL;
117 binding BASS_GET_CPU fn BASS_GetCPU() -> f32;
118 binding BASS_START fn BASS_Start() -> BOOL;
119 binding BASS_STOP fn BASS_Stop() -> BOOL;
120 binding BASS_PAUSE fn BASS_Pause() -> BOOL;
121 binding BASS_IS_STARTED fn BASS_IsStarted() -> DWORD;
122 binding BASS_SET_VOLUME fn BASS_SetVolume(value: f32) -> BOOL;
123 binding BASS_GET_VOLUME fn BASS_GetVolume() -> f32;
124 binding BASS_PLUGIN_LOAD fn BASS_PluginLoad(file: *const c_void, flags: DWORD) -> HPLUGIN;
125 binding BASS_PLUGIN_FREE fn BASS_PluginFree(handle: HPLUGIN) -> BOOL;
126 binding BASS_PLUGIN_ENABLE fn BASS_PluginEnable(handle: HPLUGIN, enable: BOOL) -> BOOL;
127 binding BASS_PLUGIN_GET_INFO fn BASS_PluginGetInfo(handle: HPLUGIN) -> *mut BassPluginInfo;
128 binding BASS_SET_3D_FACTORS fn BASS_Set3DFactors(distance: f32, roll: f32, doppler_factor: f32) -> BOOL;
129 binding BASS_GET_3D_FACTORS fn BASS_Get3DFactors(distance: *mut f32, roll: *mut f32, doppler_factor: *mut f32) -> BOOL;
130 binding BASS_SET_3D_POSITION fn BASS_Set3DPosition(
131 position: *const Bass3DVector,
132 velocity: *const Bass3DVector,
133 front: *const Bass3DVector,
134 top: *const Bass3DVector
135 ) -> BOOL;
136 binding BASS_GET_3D_POSITION fn BASS_Get3DPosition(
137 position: *mut Bass3DVector,
138 velocity: *mut Bass3DVector,
139 front: *mut Bass3DVector,
140 top: *mut Bass3DVector
141 ) -> BOOL;
142 binding BASS_APPLY_3D fn BASS_Apply3D();
143 binding BASS_MUSIC_LOAD fn BASS_MusicLoad(
144 memory: BOOL,
145 file: *const c_void,
146 offset: QWORD,
147 length: DWORD,
148 flags: DWORD,
149 frequency: DWORD
150 ) -> HMUSIC;
151 binding BASS_MUSIC_FREE fn BASS_MusicFree(handle: HMUSIC) -> BOOL;
152 binding BASS_SAMPLE_LOAD fn BASS_SampleLoad(
153 memory: BOOL,
154 file: *const c_void,
155 offset: QWORD,
156 length: DWORD,
157 maximum: DWORD,
158 flags: DWORD
159 ) -> HSAMPLE;
160 binding BASS_SAMPLE_CREATE fn BASS_SampleCreate(
161 length: DWORD,
162 frequency: DWORD,
163 channels: DWORD,
164 maximum: DWORD,
165 flags: DWORD
166 ) -> HSAMPLE;
167 binding BASS_SAMPLE_FREE fn BASS_SampleFree(handle: HSAMPLE) -> BOOL;
168 binding BASS_SAMPLE_SET_DATA fn BASS_SampleSetData(handle: HSAMPLE, buffer: *const c_void) -> BOOL;
169 binding BASS_SAMPLE_GET_DATA fn BASS_SampleGetData(handle: HSAMPLE, buffer: *mut c_void) -> BOOL;
170 binding BASS_SAMPLE_GET_INFO fn BASS_SampleGetInfo(handle: HSAMPLE, info: *mut BassSample) -> BOOL;
171 binding BASS_SAMPLE_SET_INFO fn BASS_SampleSetInfo(handle: HSAMPLE, info: *const BassSample) -> BOOL;
172 binding BASS_SAMPLE_GET_CHANNEL fn BASS_SampleGetChannel(handle: HSAMPLE, flags: DWORD) -> HCHANNEL;
173 binding BASS_SAMPLE_GET_CHANNELS fn BASS_SampleGetChannels(handle: HSAMPLE, channels: *mut HCHANNEL) -> DWORD;
174 binding BASS_SAMPLE_STOP fn BASS_SampleStop(handle: HSAMPLE) -> BOOL;
175 binding BASS_STREAM_CREATE fn BASS_StreamCreate(
176 frequency: DWORD,
177 channels: DWORD,
178 flags: DWORD,
179 proc: *mut STREAMPROC,
180 user: *mut c_void
181 ) -> HSTREAM;
182 binding BASS_STREAM_CREATE_FILE fn BASS_StreamCreateFile(
183 memory: BOOL,
184 file: *const c_void,
185 offset: QWORD,
186 length: QWORD,
187 flags: DWORD
188 ) -> HSTREAM;
189 binding BASS_STREAM_CREATE_URL fn BASS_StreamCreateURL(
190 url: *const c_char,
191 offset: DWORD,
192 flags: DWORD,
193 proc: *mut DOWNLOADPROC,
194 user: *mut c_void
195 ) -> HSTREAM;
196 binding BASS_STREAM_CREATE_FILE_USER fn BASS_StreamCreateFileUser(
197 system: DWORD,
198 flags: DWORD,
199 proc: *mut BassFileProcs,
200 user: *mut c_void
201 ) -> HSTREAM;
202 binding BASS_STREAM_FREE fn BASS_StreamFree(handle: HSTREAM) -> BOOL;
203 binding BASS_STREAM_GET_FILE_POSITION fn BASS_StreamGetFilePosition(handle: HSTREAM, mode: DWORD) -> QWORD;
204 binding BASS_STREAM_PUT_DATA fn BASS_StreamPutData(handle: HSTREAM, buffer: *const c_void, length: DWORD) -> DWORD;
205 binding BASS_STREAM_PUT_FILE_DATA fn BASS_StreamPutFileData(handle: HSTREAM, buffer: *const c_void, length: DWORD) -> DWORD;
206 binding BASS_RECORD_GET_DEVICE_INFO fn BASS_RecordGetDeviceInfo(device: DWORD, info: *mut BassDeviceInfo) -> BOOL;
207 binding BASS_RECORD_INIT fn BASS_RecordInit(device: c_int) -> BOOL;
208 binding BASS_RECORD_SET_DEVICE fn BASS_RecordSetDevice(device: DWORD) -> BOOL;
209 binding BASS_RECORD_GET_DEVICE fn BASS_RecordGetDevice() -> DWORD;
210 binding BASS_RECORD_FREE fn BASS_RecordFree() -> BOOL;
211 binding BASS_RECORD_GET_INFO fn BASS_RecordGetInfo(info: *mut BassRecordInfo) -> BOOL;
212 binding BASS_RECORD_GET_INPUT_NAME fn BASS_RecordGetInputName(input: c_int) -> *const c_void;
213 binding BASS_RECORD_SET_INPUT fn BASS_RecordSetInput(input: c_int, flags: DWORD, volume: f32) -> BOOL;
214 binding BASS_RECORD_GET_INPUT fn BASS_RecordGetInput(input: c_int, volume: *mut f32) -> DWORD;
215 binding BASS_RECORD_START fn BASS_RecordStart(
216 frequency: DWORD,
217 channels: DWORD,
218 flags: DWORD,
219 proc: *mut RECORDPROC,
220 user: *mut c_void
221 ) -> HRECORD;
222 binding BASS_CHANNEL_BYTES_TO_SECONDS fn BASS_ChannelBytes2Seconds(handle: DWORD, position: QWORD) -> f64;
223 binding BASS_CHANNEL_SECONDS_TO_BYTES fn BASS_ChannelSeconds2Bytes(handle: DWORD, position: f64) -> QWORD;
224 binding BASS_CHANNEL_GET_DEVICE fn BASS_ChannelGetDevice(handle: DWORD) -> DWORD;
225 binding BASS_CHANNEL_SET_DEVICE fn BASS_ChannelSetDevice(handle: DWORD, device: DWORD) -> BOOL;
226 binding BASS_CHANNEL_IS_ACTIVE fn BASS_ChannelIsActive(handle: DWORD) -> DWORD;
227 binding BASS_CHANNEL_GET_INFO fn BASS_ChannelGetInfo(handle: DWORD, info: *mut BassChannelInfo) -> BOOL;
228 binding BASS_CHANNEL_GET_TAGS fn BASS_ChannelGetTags(handle: DWORD, tags: DWORD) -> *const c_char;
229 binding BASS_CHANNEL_FLAGS fn BASS_ChannelFlags(handle: DWORD, flags: DWORD, mask: DWORD) -> DWORD;
230 binding BASS_CHANNEL_UPDATE fn BASS_ChannelUpdate(handle: DWORD, length: DWORD) -> BOOL;
231 binding BASS_CHANNEL_LOCK fn BASS_ChannelLock(handle: DWORD, lock: BOOL) -> BOOL;
232 binding BASS_CHANNEL_FREE fn BASS_ChannelFree(handle: DWORD) -> BOOL;
233 binding BASS_CHANNEL_PLAY fn BASS_ChannelPlay(handle: DWORD, restart: BOOL) -> BOOL;
234 binding BASS_CHANNEL_STOP fn BASS_ChannelStop(handle: DWORD) -> BOOL;
235 binding BASS_CHANNEL_PAUSE fn BASS_ChannelPause(handle: DWORD) -> BOOL;
236 binding BASS_CHANNEL_SET_ATTRIBUTE fn BASS_ChannelSetAttribute(handle: DWORD, attribute: DWORD, value: f32) -> BOOL;
237 binding BASS_CHANNEL_GET_ATTRIBUTE fn BASS_ChannelGetAttribute(handle: DWORD, attribute: DWORD, value: *mut f32) -> BOOL;
238 binding BASS_CHANNEL_SLIDE_ATTRIBUTE fn BASS_ChannelSlideAttribute(handle: DWORD, attribute: DWORD, value: f32, time: DWORD)-> BOOL;
239 binding BASS_CHANNEL_IS_SLIDING fn BASS_ChannelIsSliding(handle: DWORD, attribute: DWORD) -> BOOL;
240 binding BASS_CHANNEL_SET_ATTRIBUTE_EX fn BASS_ChannelSetAttributeEx(
241 handle: DWORD,
242 attribute: DWORD,
243 value: *mut c_void,
244 size: DWORD
245 ) -> BOOL;
246 binding BASS_CHANNEL_GET_ATTRIBUTE_EX fn BASS_ChannelGetAttributeEx(
247 handle: DWORD,
248 attribute: DWORD,
249 value: *mut c_void,
250 size: DWORD
251 ) -> DWORD;
252 binding BASS_CHANNEL_SET_3D_ATTRIBUTES fn BASS_ChannelSet3DAttributes(
253 handle: DWORD,
254 mode: c_int,
255 minimum: f32,
256 maximum: f32,
257 iangle: c_int,
258 oangle: c_int,
259 out_volume: f32
260 ) -> BOOL;
261 binding BASS_CHANNEL_GET_3D_ATTRIBUTES fn BASS_ChannelGet3DAttributes(
262 handle: DWORD,
263 mode: *mut DWORD,
264 minimum: *mut f32,
265 maximum: *mut f32,
266 angle_of_inside_projection_cone: *mut DWORD,
267 angle_of_outside_projection_cone: *mut DWORD,
268 output_volume: *mut f32
269 ) -> BOOL;
270 binding BASS_CHANNEL_SET_3D_POSITION fn BASS_ChannelSet3DPosition(
271 handle: DWORD,
272 position: *const Bass3DVector,
273 orientation: *const Bass3DVector,
274 velocity: *const Bass3DVector
275 ) -> BOOL;
276 binding BASS_CHANNEL_GET_3D_POSITION fn BASS_ChannelGet3DPosition(
277 handle: DWORD,
278 position: *mut Bass3DVector,
279 orientation: *mut Bass3DVector,
280 velocity: *mut Bass3DVector
281 ) -> BOOL;
282 binding BASS_CHANNEL_GET_LENGTH fn BASS_ChannelGetLength(handle: DWORD, mode: DWORD) -> QWORD;
283 binding BASS_CHANNEL_SET_POSITION fn BASS_ChannelSetPosition(handle: DWORD, position: QWORD, mode: DWORD) -> BOOL;
284 binding BASS_CHANNEL_GET_POSITION fn BASS_ChannelGetPosition(handle: DWORD, mode: DWORD) -> QWORD;
285 binding BASS_CHANNEL_GET_LEVEL fn BASS_ChannelGetLevel(handle: DWORD) -> DWORD;
286 binding BASS_CHANNEL_GET_LEVEL_EX fn BASS_ChannelGetLevelEx(handle: DWORD, levels: *mut f32, length: f32, flags: DWORD) -> BOOL;
287 binding BASS_CHANNEL_GET_DATA fn BASS_ChannelGetData(handle: DWORD, buffer: *mut c_void, length: DWORD) -> DWORD;
288 binding BASS_CHANNEL_SET_SYNC fn BASS_ChannelSetSync(
289 handle: DWORD,
290 sync_type: DWORD,
291 parameter: QWORD,
292 proc: *mut SYNCPROC,
293 user: *mut c_void
294 ) -> HSYNC;
295 binding BASS_CHANNEL_REMOVE_SYNC fn BASS_ChannelRemoveSync(handle: DWORD, sync: HSYNC) -> BOOL;
296 binding BASS_CHANNEL_SET_DSP fn BASS_ChannelSetDSP(handle: DWORD, proc: *mut DSPPROC, user: *mut c_void, priority: c_int) -> HDSP;
297 binding BASS_CHANNEL_REMOVE_DSP fn BASS_ChannelRemoveDSP(handle: DWORD, dsp: HDSP) -> BOOL;
298 binding BASS_CHANNEL_SET_LINK fn BASS_ChannelSetLink(handle: DWORD, channel: DWORD) -> BOOL;
299 binding BASS_CHANNEL_REMOVE_LINK fn BASS_ChannelRemoveLink(handle: DWORD, channel: DWORD) -> BOOL;
300 binding BASS_CHANNEL_SET_FX fn BASS_ChannelSetFX(handle: DWORD, fx_type: DWORD, priority: c_int) -> HFX;
301 binding BASS_CHANNEL_REMOVE_FX fn BASS_ChannelRemoveFX(handle: DWORD, fx: HFX) -> BOOL;
302 binding BASS_FX_SET_PARAMETERS fn BASS_FXSetParameters(handle: HFX, parameters: *const c_void) -> BOOL;
303 binding BASS_FX_GET_PARAMETERS fn BASS_FXGetParameters(handle: HFX, parameters: *mut c_void) -> BOOL;
304 binding BASS_FX_RESET fn BASS_FXReset(handle: HFX);
305 binding BASS_FX_SET_PRIORITY fn BASS_FXSetPriority(handle: HFX, priority: c_int) -> BOOL;
306}