1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use bincode::ErrorKind;
use serde::{Deserialize, Serialize};

use libflate::deflate::*;
use std::io::{Read, Write};
use std::sync::Arc;

use crate::instrument::Instrument;
use crate::patternslot::PatternSlot;

pub const DEFAULT_PATTERN_LENGTH: usize = 64;
pub const MAX_NUM_ROWS: usize = 256;

/// Historical Frequencies to load old data. Default is Linear.
#[derive(Serialize, Deserialize, Clone, Copy, Debug)]
pub enum FrequencyType {
    AmigaFrequencies,
    LinearFrequencies,
}

impl Default for FrequencyType {
    fn default() -> Self {
        Self::LinearFrequencies
    }
}

/// A row contains its column elements
pub type Row = Vec<PatternSlot>;

/// Patterns are sequences of lines
pub type Pattern = Vec<Row>;

/// SoundTracker Module with Steroid
#[derive(Serialize, Deserialize, Debug)]
pub struct Module {
    pub name: String,
    pub comment: String,
    pub frequency_type: FrequencyType,
    /// Restart index in `pattern_order`
    pub restart_position: u16,
    pub default_tempo: u16,
    pub default_bpm: u16,
    /// Defines the exact order for the patterns playback
    pub pattern_order: Vec<u8>,
    pub pattern: Vec<Arc<Pattern>>,
    /// Instrument 1 has index 0, instrument 2 has index 1, etc.
    pub instrument: Vec<Arc<Instrument>>,
}

impl Default for Module {
    fn default() -> Self {
        Module {
            name: "".to_string(),
            comment: "".to_string(),
            frequency_type: FrequencyType::LinearFrequencies,
            restart_position: 0,
            default_tempo: 6,
            default_bpm: 125,
            pattern_order: vec![],
            pattern: vec![],
            instrument: vec![],
        }
    }
}

impl Module {
    /// Load module using bincode
    pub fn load(data: &[u8]) -> Result<Module, Box<ErrorKind>> {
        let version = env!("CARGO_PKG_VERSION_MAJOR");
        let mut header: [u8; 5] = *b"XMrs ";
        header[4] = version.as_bytes()[0];

        let ver_data = &data[0..5];
        let real_data = &data[5..];
        if ver_data != header {
            Err(Box::new(ErrorKind::Custom(
                "Bad Module version".to_string(),
            )))
        } else {
            let mut decoder = Decoder::new(real_data);
            let mut decoded_data = Vec::new();
            decoder.read_to_end(&mut decoded_data).unwrap();

            Ok(bincode::deserialize(&decoded_data)?)
        }
    }

    /// Save module using bincode
    pub fn save(&self) -> Result<Vec<u8>, Box<ErrorKind>> {
        let version = env!("CARGO_PKG_VERSION_MAJOR");
        let mut header: [u8; 5] = *b"XMrs ";
        header[4] = version.as_bytes()[0];

        let mut ser_all = header.to_vec();

        let ser_mod1 = bincode::serialize(&self)?;
        let mut encoder = Encoder::new(Vec::new());
        encoder.write_all(&ser_mod1)?;
        let mut ser_mod2 = encoder.finish().into_result()?;

        ser_all.append(&mut ser_mod2);

        Ok(ser_all)
    }

    /// get song length
    pub fn get_song_length(&self) -> usize {
        self.pattern_order.len()
    }

    /// get number of channels
    pub fn get_num_channels(&self) -> usize {
        if self.pattern.len() != 0 {
            self.pattern[0][0].len()
        } else {
            0
        }
    }

    /// get number of rows
    pub fn get_num_rows(&self, pat_idx: usize) -> usize {
        if self.pattern.len() != 0 {
            self.pattern[pat_idx].len()
        } else {
            0
        }
    }
}