Upgrade xmrs which gives us s3m and mod file support (#767)

Closes #742

Turns out XMRS will do the conversion for us, which means we can 'just
support' s3m and mod file formats for free which is nice.

- [x] Changelog updated / no changelog update needed
This commit is contained in:
Gwilym Inzani 2024-09-25 10:33:37 +01:00 committed by GitHub
commit d6bc6f49b4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 57 additions and 17 deletions

View file

@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- Added support for s3m and mod format files to `agb-tracker`.
## [0.21.0] - 2024/09/24
### Added

View file

@ -79,6 +79,14 @@ use agb_fixnum::Num;
#[cfg(feature = "xm")]
pub use agb_xm::include_xm;
/// Import an S3M file. Only available if you have the `xm` feature enabled (enabled by default).
#[cfg(feature = "xm")]
pub use agb_xm::include_s3m;
/// Import a MOD file. Only available if you have the `xm` feature enabled (enabled by default).
#[cfg(feature = "xm")]
pub use agb_xm::include_mod;
/// Import a midi file. Only available if you have the `midi` feature enabled (enabled by default).
/// This is currently experimental, and many types of MIDI file or MIDI features are not supported.
///

View file

@ -16,4 +16,4 @@ syn = "2"
agb_tracker_interop = { version = "0.21.0", path = "../agb-tracker-interop", default-features = false }
agb_fixnum = { version = "0.21.0", path = "../../agb-fixnum" }
xmrs = { version = "0.6.1", features = ["std"] }
xmrs = { version = "0.7.2", features = ["std"] }

View file

@ -19,4 +19,4 @@ proc-macro2 = "1"
quote = "1"
syn = "2"
xmrs = "0.6"
xmrs = "0.7"

View file

@ -5,15 +5,33 @@ use proc_macro::TokenStream;
use proc_macro_error::{abort, proc_macro_error};
use quote::quote;
use syn::LitStr;
use xmrs::{module::Module, xm::xmmodule::XmModule};
use xmrs::{
amiga::amiga_module::AmigaModule, module::Module, s3m::s3m_module::S3mModule,
xm::xmmodule::XmModule,
};
#[proc_macro_error]
#[proc_macro]
pub fn include_xm(args: TokenStream) -> TokenStream {
agb_xm_core(args)
agb_xm_core(args, |content| Ok(XmModule::load(content)?.to_module()))
}
fn agb_xm_core(args: TokenStream) -> TokenStream {
#[proc_macro_error]
#[proc_macro]
pub fn include_s3m(args: TokenStream) -> TokenStream {
agb_xm_core(args, |content| Ok(S3mModule::load(content)?.to_module()))
}
#[proc_macro_error]
#[proc_macro]
pub fn include_mod(args: TokenStream) -> TokenStream {
agb_xm_core(args, |content| Ok(AmigaModule::load(content)?.to_module()))
}
fn agb_xm_core(
args: TokenStream,
load_module: impl Fn(&[u8]) -> Result<Module, Box<dyn Error>>,
) -> TokenStream {
let input = match syn::parse::<LitStr>(args) {
Ok(input) => input,
Err(err) => return err.to_compile_error().into(),
@ -26,7 +44,12 @@ fn agb_xm_core(args: TokenStream) -> TokenStream {
let include_path = path.to_string_lossy();
let module = match load_module_from_file(&path) {
let file_content = match fs::read(&path) {
Ok(content) => content,
Err(e) => abort!(input, e),
};
let module = match load_module(&file_content) {
Ok(track) => track,
Err(e) => abort!(input, e),
};
@ -42,8 +65,3 @@ fn agb_xm_core(args: TokenStream) -> TokenStream {
}
.into()
}
fn load_module_from_file(xm_path: &Path) -> Result<Module, Box<dyn Error>> {
let file_content = fs::read(xm_path)?;
Ok(XmModule::load(&file_content)?.to_module())
}

View file

@ -12,6 +12,7 @@ agb_xm_core = { version = "0.21.0", path = "../agb-xm-core" }
agb_tracker = { version = "0.21.0", path = "../agb-tracker", default-features = false }
agb_fixnum = { version = "0.21.0", path = "../../agb-fixnum" }
xmrs = "0.6"
anyhow = "1"
xmrs = "0.7"
cpal = "0.15"

View file

@ -1,15 +1,18 @@
use std::{env, error::Error, fs, path::Path, sync::mpsc};
use std::{env, fs, path::Path, sync::mpsc};
use cpal::{
traits::{DeviceTrait, HostTrait, StreamTrait},
SampleFormat, SampleRate,
};
use mixer::Mixer;
use xmrs::{module::Module, xm::xmmodule::XmModule};
use xmrs::{
amiga::amiga_module::AmigaModule, module::Module, s3m::s3m_module::S3mModule,
xm::xmmodule::XmModule,
};
mod mixer;
fn main() -> Result<(), Box<dyn Error>> {
fn main() -> anyhow::Result<()> {
let args: Vec<String> = env::args().collect();
let file_path = &args[1];
@ -60,7 +63,13 @@ fn main() -> Result<(), Box<dyn Error>> {
}
}
fn load_module_from_file(xm_path: &Path) -> Result<Module, Box<dyn Error>> {
fn load_module_from_file(xm_path: &Path) -> anyhow::Result<Module> {
let file_content = fs::read(xm_path)?;
Ok(XmModule::load(&file_content)?.to_module())
match xm_path.extension().and_then(|ex| ex.to_str()) {
Some("xm") => Ok(XmModule::load(&file_content)?.to_module()),
Some("s3m") => Ok(S3mModule::load(&file_content)?.to_module()),
Some("mod") => Ok(AmigaModule::load(&file_content)?.to_module()),
ex => anyhow::bail!("Invalid file extension {ex:?}"),
}
}