fmod/core/system/filesystem.rs
1// Copyright (c) 2024 Melody Madeline Lyons
2//
3// This Source Code Form is subject to the terms of the Mozilla Public
4// License, v. 2.0. If a copy of the MPL was not distributed with this
5// file, You can obtain one at https://mozilla.org/MPL/2.0/.
6
7use std::ffi::c_int;
8
9use crate::{
10 FileSystemAsync, FileSystemSync, async_filesystem_cancel, async_filesystem_read,
11 filesystem_close, filesystem_open, filesystem_read, filesystem_seek,
12};
13use crate::{FmodResultExt, Result};
14use fmod_sys::*;
15
16use super::System;
17
18#[cfg(doc)]
19use crate::Sound;
20
21impl System {
22 /// Set callbacks to implement all file I/O instead of using the platform native method.
23 ///
24 /// Setting these callbacks have no effect on sounds loaded with [`FMOD_OPENMEMORY`] or [`FMOD_OPENUSER`].
25 ///
26 /// Setting blockalign to 0 will disable file buffering and cause every read to invoke the relevant callback (not recommended),
27 /// current default is tuned for memory usage vs performance.
28 /// Be mindful of the I/O capabilities of the platform before increasing this default.
29 pub fn set_default_filesystem(&self, block_align: c_int) -> Result<()> {
30 unsafe {
31 FMOD_System_SetFileSystem(
32 self.inner.as_ptr(),
33 None,
34 None,
35 None,
36 None,
37 None,
38 None,
39 block_align,
40 )
41 .to_result()
42 }
43 }
44
45 /// Set callbacks to implement all file I/O instead of using the platform native method.
46 ///
47 /// Setting these callbacks have no effect on sounds loaded with [`FMOD_OPENMEMORY`] or [`FMOD_OPENUSER`].
48 ///
49 /// Setting blockalign to 0 will disable file buffering and cause every read to invoke the relevant callback (not recommended),
50 /// current default is tuned for memory usage vs performance.
51 /// Be mindful of the I/O capabilities of the platform before increasing this default.
52 pub fn set_filesystem_sync<F: FileSystemSync>(&self, block_align: c_int) -> Result<()> {
53 unsafe {
54 FMOD_System_SetFileSystem(
55 self.inner.as_ptr(),
56 Some(filesystem_open::<F>),
57 Some(filesystem_close::<F>),
58 Some(filesystem_read::<F>),
59 Some(filesystem_seek::<F>),
60 None,
61 None,
62 block_align,
63 )
64 .to_result()
65 }
66 }
67
68 /// Set callbacks to implement all file I/O instead of using the platform native method.
69 ///
70 /// Setting these callbacks have no effect on sounds loaded with [`FMOD_OPENMEMORY`] or [`FMOD_OPENUSER`].
71 ///
72 /// Setting blockalign to 0 will disable file buffering and cause every read to invoke the relevant callback (not recommended),
73 /// current default is tuned for memory usage vs performance.
74 /// Be mindful of the I/O capabilities of the platform before increasing this default.
75 /// - it is recommended to consult the 'asyncio' example for reference implementation.
76 /// There is also a tutorial on the subject, Asynchronous I/O.
77 /// - [`FileSystemAsync::read`] allows the user to return immediately before the data is ready.
78 /// FMOD will either wait internally (see note below about thread safety), or continuously check in the streamer until data arrives.
79 /// It is the user's responsibility to provide data in time in the stream case, or the stream may stutter.
80 /// Data starvation can be detected with [`Sound::get_open_state`].
81 /// - Important: If [`FileSystemAsync::read`] is processed in the main thread, then it will hang the application,
82 /// because FMOD will wait internally until data is ready, and the main thread will not be able to supply the data.
83 /// For this reason the user's file access should normally be from a separate thread.
84 /// - A [`FileSystemAsync::cancel`] must either service or prevent an async read issued previously via [`FileSystemAsync::read`] before returning.
85 pub fn set_filesystem_async<F: FileSystemAsync>(&self, block_align: c_int) -> Result<()> {
86 unsafe {
87 FMOD_System_SetFileSystem(
88 self.inner.as_ptr(),
89 Some(filesystem_open::<F>),
90 Some(filesystem_close::<F>),
91 None,
92 None,
93 Some(async_filesystem_read::<F>),
94 Some(async_filesystem_cancel::<F>),
95 block_align,
96 )
97 .to_result()
98 }
99 }
100
101 /// 'Piggyback' on FMOD file reading routines to capture data as it's read.
102 ///
103 /// This allows users to capture data as FMOD reads it,
104 /// which may be useful for extracting the raw data that FMOD reads for hard to support sources (for example internet streams).
105 ///
106 /// Note: This function is not to replace FMOD's file system. For this functionality, see [`System::set_filesystem_sync`].
107 pub fn attach_filesystem<F: FileSystemSync>(&self) -> Result<()> {
108 unsafe {
109 FMOD_System_AttachFileSystem(
110 self.inner.as_ptr(),
111 Some(filesystem_open::<F>),
112 Some(filesystem_close::<F>),
113 Some(filesystem_read::<F>),
114 Some(filesystem_seek::<F>),
115 )
116 .to_result()
117 }
118 }
119
120 /// Detach the currently attached listener filesystem.
121 pub fn detach_filesystem(&self) -> Result<()> {
122 unsafe {
123 FMOD_System_AttachFileSystem(self.inner.as_ptr(), None, None, None, None).to_result()
124 }
125 }
126}