diff --git a/tracker/agb-midi-core/Cargo.toml b/tracker/agb-midi-core/Cargo.toml new file mode 100644 index 00000000..125097d9 --- /dev/null +++ b/tracker/agb-midi-core/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "agb_midi_core" +version = "0.18.0" +authors = ["Gwilym Inzani "] +edition = "2021" +license = "MPL-2.0" +description = "Library for converting MIDI files for use with agb-tracker on the Game Boy Advance. You shouldn't use this package directly" +repository = "https://github.com/agbrs/agb" + +[dependencies] +proc-macro-error = "1" +proc-macro2 = "1" +quote = "1" +syn = "2" +rustysynth = "1.3" +midly = { version = "0.5", default-features = false, features = [ + "alloc", + "std", +] } + +agb_tracker_interop = { version = "0.18.0", path = "../agb-tracker-interop" } +agb_fixnum = { version = "0.18.0", path = "../../agb-fixnum" } diff --git a/tracker/agb-midi-core/src/lib.rs b/tracker/agb-midi-core/src/lib.rs new file mode 100644 index 00000000..f71079b5 --- /dev/null +++ b/tracker/agb-midi-core/src/lib.rs @@ -0,0 +1,70 @@ +use std::{error::Error, path::Path}; + +use proc_macro2::TokenStream; +use proc_macro_error::abort; +use quote::quote; +use syn::{ + parse::{Parse, ParseStream}, + LitStr, Token, +}; + +struct MidiCoreInput { + sf2_file: LitStr, + comma: Token![,], + midi_file: LitStr, +} + +impl Parse for MidiCoreInput { + fn parse(input: ParseStream) -> syn::Result { + Ok(Self { + sf2_file: input.parse()?, + comma: input.parse()?, + midi_file: input.parse()?, + }) + } +} + +pub fn agb_midi_core(args: TokenStream) -> TokenStream { + let input: MidiCoreInput = match syn::parse2(args.clone()) { + Ok(input) => input, + Err(e) => abort!(args, e), + }; + + let sf2_file = input.sf2_file.value(); + let midi_file = input.midi_file.value(); + + let root = std::env::var("CARGO_MANIFEST_DIR").expect("Failed to get cargo manifest dir"); + let sf2_file = Path::new(&root).join(&*sf2_file); + let midi_file = Path::new(&root).join(&*midi_file); + + let sf2_include_path = sf2_file.to_string_lossy(); + let midi_file_include_path = midi_file.to_string_lossy(); + + let midi_info = match MidiInfo::load_from_file(&sf2_file, &midi_file) { + Ok(track) => track, + Err(e) => abort!(args, e), + }; + + let parsed = parse_midi(&midi_info); + + quote! { + { + const _: &[u8] = include_bytes!(#sf2_include_path); + const _: &[u8] = include_bytes!(#midi_file_include_path); + + #parsed + } + } +} + +pub struct MidiInfo {} + +impl MidiInfo { + pub fn load_from_file(sf2_file: &Path, midi_file: &Path) -> Result> { + Ok(Self {}) + } +} + +pub fn parse_midi(midi_info: &MidiInfo) -> TokenStream { + quote! {} +} diff --git a/tracker/agb-midi/Cargo.toml b/tracker/agb-midi/Cargo.toml new file mode 100644 index 00000000..a0060503 --- /dev/null +++ b/tracker/agb-midi/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "agb_midi" +version = "0.18.0" +authors = ["Gwilym Inzani "] +edition = "2021" +license = "MPL-2.0" +description = "Library for converting MIDI files for use with agb-tracker on the Game Boy Advance. You shouldn't use this package directly" +repository = "https://github.com/agbrs/agb" + +[lib] +proc-macro = true + +[dependencies] +agb_midi_core = { version = "0.18.0", path = "../agb-midi-core" } +proc-macro-error = "1" +proc-macro2 = "1" diff --git a/tracker/agb-midi/src/lib.rs b/tracker/agb-midi/src/lib.rs new file mode 100644 index 00000000..37429939 --- /dev/null +++ b/tracker/agb-midi/src/lib.rs @@ -0,0 +1,8 @@ +use proc_macro::TokenStream; +use proc_macro_error::proc_macro_error; + +#[proc_macro_error] +#[proc_macro] +pub fn include_xm(args: TokenStream) -> TokenStream { + agb_midi_core::agb_midi_core(args.into()).into() +} diff --git a/tracker/agb-tracker/Cargo.toml b/tracker/agb-tracker/Cargo.toml index 03c46a66..33c8eda7 100644 --- a/tracker/agb-tracker/Cargo.toml +++ b/tracker/agb-tracker/Cargo.toml @@ -8,10 +8,12 @@ description = "Library for playing tracker music. Designed for use with the agb repository = "https://github.com/agbrs/agb" [features] -default = ["xm"] +default = ["xm", "midi"] xm = ["dep:agb_xm"] +midi = ["dep:agb_midi"] [dependencies] +agb_midi = { version = "0.18.1", path = "../agb-midi", optional = true } agb_xm = { version = "0.18.1", path = "../agb-xm", optional = true } agb = { version = "0.18.1", path = "../../agb" } agb_tracker_interop = { version = "0.18.1", path = "../agb-tracker-interop", default-features = false }