use binrw::{binrw, io::Cursor, BinWrite, Endian, NullString, WriteOptions};
#[binrw]
#[derive(Debug, PartialEq, Eq)]
#[brw(little)]
#[bw(import(no_checksum: bool))]
pub struct Setting {
#[br(temp, assert(len_stringdata == 0x60))]
#[bw(calc = 0x60)]
len_stringdata: u32,
#[brw(pad_size_to = 0x20, assert(brand.len() <= (0x20 - 1)))]
pub brand: NullString,
#[brw(pad_size_to = 0x20, assert(software.len() <= (0x20 - 1)))]
pub software: NullString,
#[brw(pad_size_to = 0x20, assert(version.len() <= (0x20 - 1)))]
pub version: NullString,
#[br(temp)]
#[bw(calc = data.size())]
len_data: u32,
#[br(args(len_data))]
pub data: SettingData,
#[br(temp)]
#[bw(calc = no_checksum.then_some(0).unwrap_or_else(|| self.calculate_checksum()))]
checksum: u16,
#[br(assert(unknown == 0))]
unknown: u16,
}
impl Setting
where
Setting: BinWrite,
{
fn calculate_checksum(&self) -> u16 {
let mut data = Vec::<u8>::with_capacity(156);
let mut writer = Cursor::new(&mut data);
self.write_options(&mut writer, &WriteOptions::new(Endian::Little), (true,))
.unwrap();
let start = match self.data {
SettingData::DJMMySetting(_) => 0,
_ => 104,
};
let end = data.len() - 4;
crc16::State::<crc16::XMODEM>::calculate(&data[start..end])
}
}
#[binrw]
#[derive(Debug, PartialEq, Eq)]
#[brw(little)]
#[br(import(len: u32))]
pub enum SettingData {
#[br(pre_assert(len == 32))]
DevSetting(DevSetting),
#[br(pre_assert(len == 52))]
DJMMySetting(DJMMySetting),
#[br(pre_assert(len == 40))]
MySetting(MySetting),
#[br(pre_assert(len == 40))]
MySetting2(MySetting2),
}
impl SettingData {
fn size(&self) -> u32 {
match &self {
Self::DevSetting(_) => 32,
Self::DJMMySetting(_) => 52,
Self::MySetting(_) => 40,
Self::MySetting2(_) => 40,
}
}
}
#[binrw]
#[derive(Debug, PartialEq, Eq)]
#[brw(little)]
pub struct DevSetting {
#[br(assert(unknown1 == [0x78, 0x56, 0x34, 0x12, 0x01, 0x00, 0x00, 0x00, 0x01]))]
unknown1: [u8; 9],
pub overview_waveform_type: OverviewWaveformType,
pub waveform_color: WaveformColor,
#[br(assert(unknown2 == 0x01))]
unknown2: u8,
pub key_display_format: KeyDisplayFormat,
pub waveform_current_position: WaveformCurrentPosition,
#[br(assert(unknown3 == [0x00; 18]))]
unknown3: [u8; 18],
}
impl Default for DevSetting {
fn default() -> Self {
Self {
unknown1: [0x78, 0x56, 0x34, 0x12, 0x01, 0x00, 0x00, 0x00, 0x01],
overview_waveform_type: OverviewWaveformType::default(),
waveform_color: WaveformColor::default(),
key_display_format: KeyDisplayFormat::default(),
unknown2: 0x01,
waveform_current_position: WaveformCurrentPosition::default(),
unknown3: [0x00; 18],
}
}
}
#[binrw]
#[derive(Debug, PartialEq, Eq)]
#[brw(little)]
pub struct DJMMySetting {
unknown1: [u8; 12],
pub channel_fader_curve: ChannelFaderCurve,
pub crossfader_curve: CrossfaderCurve,
pub headphones_pre_eq: HeadphonesPreEQ,
pub headphones_mono_split: HeadphonesMonoSplit,
pub beat_fx_quantize: BeatFXQuantize,
pub mic_low_cut: MicLowCut,
pub talk_over_mode: TalkOverMode,
pub talk_over_level: TalkOverLevel,
pub midi_channel: MidiChannel,
pub midi_button_type: MidiButtonType,
pub display_brightness: MixerDisplayBrightness,
pub indicator_brightness: MixerIndicatorBrightness,
pub channel_fader_curve_long_fader: ChannelFaderCurveLongFader,
#[br(assert(unknown2 == [0; 27]))]
unknown2: [u8; 27],
}
impl Default for DJMMySetting {
fn default() -> Self {
Self {
unknown1: [
0x78, 0x56, 0x34, 0x12, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
],
channel_fader_curve: ChannelFaderCurve::default(),
crossfader_curve: CrossfaderCurve::default(),
headphones_pre_eq: HeadphonesPreEQ::default(),
headphones_mono_split: HeadphonesMonoSplit::default(),
beat_fx_quantize: BeatFXQuantize::default(),
mic_low_cut: MicLowCut::default(),
talk_over_mode: TalkOverMode::default(),
talk_over_level: TalkOverLevel::default(),
midi_channel: MidiChannel::default(),
midi_button_type: MidiButtonType::default(),
display_brightness: MixerDisplayBrightness::default(),
indicator_brightness: MixerIndicatorBrightness::default(),
channel_fader_curve_long_fader: ChannelFaderCurveLongFader::default(),
unknown2: [0; 27],
}
}
}
#[binrw]
#[derive(Debug, PartialEq, Eq)]
#[brw(little)]
pub struct MySetting {
unknown1: [u8; 8],
pub on_air_display: OnAirDisplay,
pub lcd_brightness: LCDBrightness,
pub quantize: Quantize,
pub auto_cue_level: AutoCueLevel,
pub language: Language,
unknown2: u8,
pub jog_ring_brightness: JogRingBrightness,
pub jog_ring_indicator: JogRingIndicator,
pub slip_flashing: SlipFlashing,
unknown3: [u8; 3],
pub disc_slot_illumination: DiscSlotIllumination,
pub eject_lock: EjectLock,
pub sync: Sync,
pub play_mode: PlayMode,
pub quantize_beat_value: QuantizeBeatValue,
pub hotcue_autoload: HotCueAutoLoad,
pub hotcue_color: HotCueColor,
#[br(assert(unknown4 == 0))]
unknown4: u16,
pub needle_lock: NeedleLock,
#[br(assert(unknown5 == 0))]
unknown5: u16,
pub time_mode: TimeMode,
pub jog_mode: JogMode,
pub auto_cue: AutoCue,
pub master_tempo: MasterTempo,
pub tempo_range: TempoRange,
pub phase_meter: PhaseMeter,
#[br(assert(unknown6 == 0))]
unknown6: u16,
}
impl Default for MySetting {
fn default() -> Self {
Self {
unknown1: [0x78, 0x56, 0x34, 0x12, 0x02, 0x00, 0x00, 0x00],
on_air_display: OnAirDisplay::default(),
lcd_brightness: LCDBrightness::default(),
quantize: Quantize::default(),
auto_cue_level: AutoCueLevel::default(),
language: Language::default(),
unknown2: 0x01,
jog_ring_brightness: JogRingBrightness::default(),
jog_ring_indicator: JogRingIndicator::default(),
slip_flashing: SlipFlashing::default(),
unknown3: [0x01, 0x01, 0x01],
disc_slot_illumination: DiscSlotIllumination::default(),
eject_lock: EjectLock::default(),
sync: Sync::default(),
play_mode: PlayMode::default(),
quantize_beat_value: QuantizeBeatValue::default(),
hotcue_autoload: HotCueAutoLoad::default(),
hotcue_color: HotCueColor::default(),
unknown4: 0x0000,
needle_lock: NeedleLock::default(),
unknown5: 0x0000,
time_mode: TimeMode::default(),
jog_mode: JogMode::default(),
auto_cue: AutoCue::default(),
master_tempo: MasterTempo::default(),
tempo_range: TempoRange::default(),
phase_meter: PhaseMeter::default(),
unknown6: 0x0000,
}
}
}
#[binrw]
#[derive(Debug, PartialEq, Eq)]
#[brw(little)]
pub struct MySetting2 {
pub vinyl_speed_adjust: VinylSpeedAdjust,
pub jog_display_mode: JogDisplayMode,
pub pad_button_brightness: PadButtonBrightness,
pub jog_lcd_brightness: JogLCDBrightness,
pub waveform_divisions: WaveformDivisions,
#[br(assert(unknown1 == [0; 5]))]
unknown1: [u8; 5],
pub waveform: Waveform,
unknown2: u8,
pub beat_jump_beat_value: BeatJumpBeatValue,
#[br(assert(unknown3 == [0; 27]))]
unknown3: [u8; 27],
}
impl Default for MySetting2 {
fn default() -> Self {
Self {
vinyl_speed_adjust: VinylSpeedAdjust::default(),
jog_display_mode: JogDisplayMode::default(),
pad_button_brightness: PadButtonBrightness::default(),
jog_lcd_brightness: JogLCDBrightness::default(),
waveform_divisions: WaveformDivisions::default(),
unknown1: [0; 5],
waveform: Waveform::default(),
unknown2: 0x81,
beat_jump_beat_value: BeatJumpBeatValue::default(),
unknown3: [0; 27],
}
}
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum PlayMode {
Continue = 0x80,
#[default]
Single,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum EjectLock {
#[default]
Unlock = 0x80,
Lock,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum NeedleLock {
Unlock = 0x80,
#[default]
Lock,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum QuantizeBeatValue {
EighthBeat = 0x83,
QuarterBeat = 0x82,
HalfBeat = 0x81,
#[default]
FullBeat = 0x80,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum HotCueAutoLoad {
Off = 0x80,
RekordboxSetting = 0x82,
#[default]
On = 0x81,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum HotCueColor {
#[default]
Off = 0x80,
On,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum AutoCueLevel {
Minus78dB = 0x87,
Minus72dB = 0x86,
Minus66dB = 0x85,
Minus60dB = 0x84,
Minus54dB = 0x83,
Minus48dB = 0x82,
Minus42dB = 0x81,
Minus36dB = 0x80,
#[default]
Memory = 0x88,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum TimeMode {
Elapsed = 0x80,
#[default]
Remain,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum AutoCue {
Off = 0x80,
#[default]
On,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum JogMode {
#[default]
Vinyl = 0x81,
CDJ = 0x80,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum TempoRange {
SixPercent = 0x80,
#[default]
TenPercent,
SixteenPercent,
Wide,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum MasterTempo {
#[default]
Off = 0x80,
On,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum Quantize {
Off = 0x80,
#[default]
On,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum Sync {
#[default]
Off = 0x80,
On,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum PhaseMeter {
#[default]
Type1 = 0x80,
Type2,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum Waveform {
#[default]
Waveform = 0x80,
PhaseMeter,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum WaveformDivisions {
TimeScale = 0x80,
#[default]
Phrase,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum VinylSpeedAdjust {
TouchRelease = 0x80,
#[default]
Touch,
Release,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum BeatJumpBeatValue {
HalfBeat = 0x80,
OneBeat,
TwoBeat,
FourBeat,
EightBeat,
#[default]
SixteenBeat,
ThirtytwoBeat,
SixtyfourBeat,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum Language {
#[default]
English = 0x81,
French,
German,
Italian,
Dutch,
Spanish,
Russian,
Korean,
ChineseSimplified,
ChineseTraditional,
Japanese,
Portuguese,
Swedish,
Czech,
Hungarian,
Danish,
Greek,
Turkish,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum LCDBrightness {
One = 0x81,
Two,
#[default]
Three,
Four,
Five,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum JogLCDBrightness {
One = 0x81,
Two,
#[default]
Three,
Four,
Five,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum JogDisplayMode {
#[default]
Auto = 0x80,
Info,
Simple,
Artwork,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum SlipFlashing {
Off = 0x80,
#[default]
On,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum OnAirDisplay {
Off = 0x80,
#[default]
On,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum JogRingBrightness {
Off = 0x80,
Dark,
#[default]
Bright,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum JogRingIndicator {
Off = 0x80,
#[default]
On,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum DiscSlotIllumination {
Off = 0x80,
Dark,
#[default]
Bright,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum PadButtonBrightness {
One = 0x81,
Two,
#[default]
Three,
Four,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum ChannelFaderCurve {
SteepTop = 0x80,
#[default]
Linear,
SteepBottom,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum CrossfaderCurve {
ConstantPower = 0x80,
SlowCut,
#[default]
FastCut,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum ChannelFaderCurveLongFader {
#[default]
Exponential = 0x80,
Smooth,
Linear,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum HeadphonesPreEQ {
#[default]
PostEQ = 0x80,
PreEQ,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum HeadphonesMonoSplit {
MonoSplit = 0x81,
#[default]
Stereo = 0x80,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum BeatFXQuantize {
Off = 0x80,
#[default]
On,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum MicLowCut {
Off = 0x80,
#[default]
On,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum TalkOverMode {
#[default]
Advanced = 0x80,
Normal,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum TalkOverLevel {
Minus24dB = 0x80,
#[default]
Minus18dB,
Minus12dB,
Minus6dB,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum MidiChannel {
#[default]
One = 0x80,
Two,
Three,
Four,
Five,
Six,
Seven,
Eight,
Nine,
Ten,
Eleven,
Twelve,
Thirteen,
Fourteen,
Fifteen,
Sixteen,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum MidiButtonType {
#[default]
Toggle = 0x80,
Trigger,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum MixerDisplayBrightness {
White = 0x80,
One,
Two,
Three,
Four,
#[default]
Five,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum MixerIndicatorBrightness {
One = 0x80,
Two,
#[default]
Three,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum WaveformColor {
#[default]
Blue = 0x01,
Rgb = 0x03,
TriBand = 0x04,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum WaveformCurrentPosition {
Left = 0x02,
#[default]
Center = 0x01,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum OverviewWaveformType {
#[default]
HalfWaveform = 0x01,
FullWaveform,
}
#[binrw]
#[derive(Debug, PartialEq, Eq, Default)]
#[brw(repr = u8)]
pub enum KeyDisplayFormat {
#[default]
Classic = 0x01,
Alphanumeric,
}