bass_sys/
functions.rs

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
58/// This function sets the library name.
59/// If not called manually, the library name and search paths are automatically set to the default values by the time you call any Bass function.
60/// If you wish to set them manually, do it before calling anything else.
61///
62/// Returns `Ok(())` if the library name wasn't already set, otherwise it returns `Err(name)`
63///
64/// The library name is used to find the dynamic library file of this name in paths set by `set_library_search_paths`.
65/// It should include the file extension as well (for example: `bass.dll`).
66///
67/// Note that the dynamic-link library file name is usually dependant on the currently run operating system,
68/// so in a multiplatform context one should use cfg to set the according library name.
69///
70/// For example:
71///
72/// ```no_run
73/// #[cfg(target_os = "windows")]
74/// bass_sys::set_library_name(String::from("bass.dll"));
75///
76/// #[cfg(target_os = "linux")]
77/// bass_sys::set_library_name(String::from("libbass.so"));
78///
79/// #[cfg(target_os = "macos")]
80/// bass_sys::set_library_name(String::from("libbass.dylib"));
81/// ```
82pub fn set_library_name(name: String) -> Result<(), String> {
83    BASS_LIBRARY_NAME.set(name)
84}
85
86/// This function sets the library search paths.
87/// If not called manually, the library name and search paths are automatically set to the default values by the time you call any Bass function.
88/// If you wish to set them manually, do it before calling anything else.
89///
90/// Returns `Ok(())` if the library search paths weren't already set, otherwise it returns `Err(search_paths)`
91///
92/// The library search paths are used to find the dynamic library file of the name set by `set_library_name`.
93pub 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}