# load.ludic - a clip the runtime can actually open. Audio.load takes a real FILESYSTEM path (it # bottoms out in AVAudioFile), not the pack-aware file_open every other asset arrives through: in a # bundle every clip loads as 0 while Fs.exists, which IS pack-aware, says it is there. So try the # runtime's path, and on 0 lift the bytes out of the pack into the cache directory and load that. export function aud_load(audio_st: mut AudioState, path: string) -> int { audio_st.tried += 1 if not is_windowed() { return 0 } var h = Audio.load(path) if h == 0 { let out = aud_unpack(path, base_name(path)) if out != null { h = Audio.load(out) } } if h != 0 { audio_st.live += 1 } return h } # how many clips were asked for and how many loaded: a silent game looks exactly like a working one # unless something says so export function aud_tried(audio_st: AudioState) -> int { return audio_st.tried } export function aud_live(audio_st: AudioState) -> int { return audio_st.live } # One packed file out to the cache, or null. A cached copy is trusted only if it is as long as the # packed one: a write interrupted halfway would otherwise play truncated for ever. export function aud_unpack(path: string, name: string) -> string { let dir = AudioFiles.cache_dir() if len(dir) == 0 { return null } Fs.mkdir(dir) let dst = dir + "/" + name let f = file_open(path, "rb") if f == null { return null } file_seek(f, 0, 2) let n = file_tell(f) file_close(f) if n <= 0 { return null } if Fs.exists(dst) and Fs.size(dst) == n { return dst } let buf = Fs.read_bytes(path) if buf == null or len(buf) < n { return null } if not Fs.write_bytes(dst, buf, n) { return null } return dst } function base_name(path: string) -> string { var i = len(path) - 1 while i >= 0 and path[i] != 47 { i -= 1 } return path[i + 1..len(path)] }