Closed garcia closed 2 years ago
StepMania's logic is in Song.cpp. We can mimic this in a separate module, maybe simfile.assets
. We should also take care to decouple this logic from the filesystem to support use cases like streaming simfiles and their assets from a ZIP.
Started on this in https://github.com/garcia/simfile/tree/directory-assets. Basic usage:
from simfile.dir import SimfileDirectory
sd = SimfileDirectory('path/to/simfile/directory') # raises if no SM/SSC found
sd.simfile # SSCSimfile if available, otherwise SMSimfile
sd.sm # SMSimfile or None; similar for sd.ssc
sd.banner # == sd.simfile.banner if available, otherwise the same path StepMania would infer, otherwise None
sd.music # same logic as above; similar for sd.background, sd.cdtitle, etc.
I also added a SimfilePack
that can be used to obtain all the simfile directory paths or SimfileDirectory
instances or plain Simfile
instances (one method for each). It should also ultimately have a .banner
that loads the same pack banner as StepMania (I believe this is the first image file in the pack directory lexicographically but need to confirm).
All of these new classes take a filesystem: AbstractFileSystem
argument that defaults to OSFileSystem
(these classes live in simfile.dir.fs
). I will also add a ZipFileSystem
for working with Python's zipfile
module, and developers can implement their own filesystem APIs for any other use cases. The API for this concept is very WIP and kind of just covers whatever os
or os.path
offerings are necessary for SimfileDirectory
to operate.
There are some idiosyncrasies in how simfiles are handled by StepMania that aren't modeled by this package at all currently. For example, if you want to load the banner for a simfile on disk, you can certainly try using
os.path
to Frankenstein the simfile's filename andsim.banner
together... but that only works if the BANNER tag is filled in, which isn't guaranteed. (For example, quite a few files in UPSMH Online have a blank BANNER tag.) If you leave the field blank, StepMania will try to find the appropriate image file on its own! This also applies to the music path.While this logic can be implemented in client code, I think it warrants inclusion as part of this package, given that processing simfile data together with audio or image data is a pretty noteworthy use case. It also helps us work toward the goal of handling any simfile that StepMania accepts.
I had an implementation section here previously, but I totally forgot that simfiles don't know their own filenames, so my proposed implementation was bogus. We would likely need a new submodule for loading a simfile's supplementary files.