128 lines
4.9 KiB
Rust
128 lines
4.9 KiB
Rust
use std::collections::HashMap;
|
|
use std::path::PathBuf;
|
|
use std::sync::Arc;
|
|
|
|
use crate::engine::{LinkState, PatternChange, SequencerSnapshot};
|
|
use crate::model;
|
|
use crate::settings::Settings;
|
|
use crate::state::StagedChange;
|
|
|
|
use super::App;
|
|
|
|
impl App {
|
|
pub fn save_settings(&self, link: &LinkState) {
|
|
let settings = Settings {
|
|
audio: crate::settings::AudioSettings {
|
|
output_device: self.audio.config.output_device.clone(),
|
|
input_device: self.audio.config.input_device.clone(),
|
|
channels: self.audio.config.channels,
|
|
buffer_size: self.audio.config.buffer_size,
|
|
max_voices: self.audio.config.max_voices,
|
|
},
|
|
display: crate::settings::DisplaySettings {
|
|
fps: self.audio.config.refresh_rate.to_fps(),
|
|
runtime_highlight: self.ui.runtime_highlight,
|
|
show_scope: self.audio.config.show_scope,
|
|
show_spectrum: self.audio.config.show_spectrum,
|
|
show_preview: self.audio.config.show_preview,
|
|
show_completion: self.ui.show_completion,
|
|
performance_mode: self.ui.performance_mode,
|
|
color_scheme: self.ui.color_scheme,
|
|
layout: self.audio.config.layout,
|
|
hue_rotation: self.ui.hue_rotation,
|
|
onboarding_dismissed: self.ui.onboarding_dismissed.clone(),
|
|
font: self.ui.font.clone(),
|
|
zoom_factor: self.ui.zoom_factor,
|
|
},
|
|
link: crate::settings::LinkSettings {
|
|
enabled: link.is_enabled(),
|
|
tempo: link.tempo(),
|
|
quantum: link.quantum(),
|
|
},
|
|
midi: crate::settings::MidiSettings {
|
|
output_devices: {
|
|
let outputs = crate::midi::list_midi_outputs();
|
|
self.midi
|
|
.selected_outputs
|
|
.iter()
|
|
.map(|opt| {
|
|
opt.and_then(|idx| outputs.get(idx).map(|d| d.name.clone()))
|
|
.unwrap_or_default()
|
|
})
|
|
.collect()
|
|
},
|
|
input_devices: {
|
|
let inputs = crate::midi::list_midi_inputs();
|
|
self.midi
|
|
.selected_inputs
|
|
.iter()
|
|
.map(|opt| {
|
|
opt.and_then(|idx| inputs.get(idx).map(|d| d.name.clone()))
|
|
.unwrap_or_default()
|
|
})
|
|
.collect()
|
|
},
|
|
},
|
|
};
|
|
settings.save();
|
|
}
|
|
|
|
pub fn save(&mut self, path: PathBuf, link: &LinkState, snapshot: &SequencerSnapshot) {
|
|
self.save_editor_to_step();
|
|
self.project_state.project.sample_paths = self.audio.config.sample_paths.clone();
|
|
self.project_state.project.tempo = link.tempo();
|
|
self.project_state.project.playing_patterns = snapshot
|
|
.active_patterns
|
|
.iter()
|
|
.map(|p| (p.bank, p.pattern))
|
|
.collect();
|
|
match model::save(&self.project_state.project, &path) {
|
|
Ok(final_path) => {
|
|
self.ui
|
|
.set_status(format!("Saved: {}", final_path.display()));
|
|
self.project_state.file_path = Some(final_path);
|
|
}
|
|
Err(e) => {
|
|
self.ui.set_status(format!("Save error: {e}"));
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn load(&mut self, path: PathBuf, link: &LinkState) {
|
|
match model::load(&path) {
|
|
Ok(project) => {
|
|
let tempo = project.tempo;
|
|
let playing = project.playing_patterns.clone();
|
|
|
|
self.project_state.project = project;
|
|
self.editor_ctx.step = 0;
|
|
self.load_step_to_editor();
|
|
self.compile_all_steps(link);
|
|
self.mark_all_patterns_dirty();
|
|
link.set_tempo(tempo);
|
|
|
|
self.playback.clear_queues();
|
|
self.undo.clear();
|
|
self.variables.store(Arc::new(HashMap::new()));
|
|
self.dict.lock().clear();
|
|
|
|
self.evaluate_prelude(link);
|
|
|
|
for (bank, pattern) in playing {
|
|
self.playback.queued_changes.push(StagedChange {
|
|
change: PatternChange::Start { bank, pattern },
|
|
quantization: crate::model::LaunchQuantization::Immediate,
|
|
sync_mode: crate::model::SyncMode::PhaseLock,
|
|
});
|
|
}
|
|
|
|
self.ui.set_status(format!("Loaded: {}", path.display()));
|
|
self.project_state.file_path = Some(path);
|
|
}
|
|
Err(e) => {
|
|
self.ui.set_status(format!("Load error: {e}"));
|
|
}
|
|
}
|
|
}
|
|
}
|