use error::NbsError;
use header::Header;
use io::{ReadStringExt, WriteStringExt};
use noteblocks::{instrument::CustomInstruments, NoteBlocks};
use std::time::Duration;
pub mod error;
pub mod header;
pub mod io;
pub mod noteblocks;
#[derive(PartialEq, Debug, Clone, Copy)]
pub enum NbsFormat {
NoteBlockStudio,
OpenNoteBlockStudio(i8),
}
impl NbsFormat {
pub fn is_new(&self) -> bool {
match self {
NbsFormat::NoteBlockStudio => false,
NbsFormat::OpenNoteBlockStudio(_) => true,
}
}
pub fn version(&self) -> i8 {
match self {
NbsFormat::NoteBlockStudio => 0,
&NbsFormat::OpenNoteBlockStudio(v) => v,
}
}
}
pub struct Nbs {
pub header: Header,
pub noteblocks: NoteBlocks,
pub custom_instruments: CustomInstruments,
}
impl Nbs {
pub fn from_componets(
header: Header,
noteblocks: NoteBlocks,
custom_instruments: CustomInstruments,
) -> Self {
Nbs {
header,
noteblocks,
custom_instruments,
}
}
pub fn decode<R>(mut reader: &mut R) -> Result<Nbs, NbsError>
where
R: ReadStringExt,
{
let header = Header::decode(&mut reader)?;
let noteblocks = NoteBlocks::decode(&mut reader, &header)?;
let custom_instruments = CustomInstruments::decode(&mut reader, &header)?;
Ok(Nbs {
header,
noteblocks,
custom_instruments,
})
}
pub fn update(&mut self) {
if self.format().version() >= 3 {
self.header.song_length = Some(self.noteblocks.calculate_length());
} else if self.format().version() == 0 {
self.header.old_song_length = self.noteblocks.calculate_length();
}
if self.format().version() > 0 {
self.header.version_number = Some(self.format().version());
}
self.header.layer_count = self.noteblocks.layers.len() as i16;
}
pub fn encode<W>(&self, mut writer: &mut W) -> Result<(), NbsError>
where
W: WriteStringExt,
{
self.header.encode(self.format(), &mut writer)?;
self.noteblocks.encode(self.format(), &mut writer)?;
self.custom_instruments.encode(&mut writer)?;
Ok(())
}
pub fn format(&self) -> NbsFormat {
return self.header.format;
}
pub fn song_ticks(&self) -> i16 {
self.noteblocks.calculate_length()
}
pub fn song_length(&self) -> Duration {
Duration::from_secs_f32(self.song_ticks() as f32 / (self.header.song_tempo as f32 / 100.0))
}
}