audio-oxide/au-o2-gui/src/editor/tracks.rs

177 lines
9.0 KiB
Rust

use iced::Task;
use super::{Editor, Message, ModalState};
use crate::engine::{EngineCommand, TransportState};
use crate::gui::editor::{new_track_wizard, track_header};
use crate::history::EditCommand;
use crate::track::Track;
impl Editor {
pub(crate) fn handle_tracks(&mut self, message: Message) -> Task<Message> {
match message {
Message::ShowNewTrackWizard => {
self.modal_state =
Some(ModalState::NewTrackWizard(new_track_wizard::State::default()));
}
Message::NewTrackWizard(wizard_message) => {
if let Some(ModalState::NewTrackWizard(state)) = &mut self.modal_state {
match wizard_message {
new_track_wizard::Message::Cancel => self.modal_state = None,
new_track_wizard::Message::Create => {
let config = state.config.clone();
let track = Track::new(config, self.track_count);
self.track_count += 1;
if let Some(ref engine) = self.engine {
engine.send(EngineCommand::CreateBus {
name: track.bus_name.clone(),
is_midi: track.track_type == crate::track::TrackType::Midi,
});
engine.send(EngineCommand::SetBusVolume {
bus_name: track.bus_name.clone(),
volume: track.volume,
});
}
let idx = self.tracks.len();
self.tracks.push(track);
self.history.push(EditCommand::CreateTrack { index: idx });
self.modal_state = None;
}
new_track_wizard::Message::NameChanged(name) => state.config.name = name,
new_track_wizard::Message::TrackTypeSelected(track_type) => {
state.config.track_type = track_type
}
}
}
}
Message::TrackHeader(i, msg) => {
if let Some(track) = self.tracks.get_mut(i) {
match msg {
track_header::Message::MuteToggled => {
track.muted = !track.muted;
if let Some(ref engine) = self.engine {
engine.send(EngineCommand::SetBusMute {
bus_name: track.bus_name.clone(),
muted: track.muted,
});
}
self.mark_dirty();
}
track_header::Message::SoloToggled => {
track.soloed = !track.soloed;
if let Some(ref engine) = self.engine {
engine.send(EngineCommand::SetBusSolo {
bus_name: track.bus_name.clone(),
soloed: track.soloed,
});
}
self.mark_dirty();
}
track_header::Message::RecordArmToggled => {
track.record_armed = !track.record_armed;
if let Some(ref engine) = self.engine {
if track.record_armed {
engine.send(EngineCommand::ArmTrack {
bus_name: track.bus_name.clone(),
});
} else {
engine.send(EngineCommand::DisarmTrack {
bus_name: track.bus_name.clone(),
});
}
}
}
track_header::Message::VolumeChanged(vol) => {
track.volume = if (vol - 0.75).abs() < 0.02 { 0.75 } else { vol };
let group_vol = track.group_id
.and_then(|gid| self.groups.iter().find(|g| g.id == gid))
.map(|g| g.volume)
.unwrap_or(1.0);
if let Some(ref engine) = self.engine {
engine.send(EngineCommand::SetBusVolume {
bus_name: track.bus_name.clone(),
volume: track.volume * group_vol,
});
}
let should_record = self.transport == TransportState::Playing && track.automation_mode.writes();
let vol_val = track.volume;
self.mark_dirty();
if should_record {
let sample_pos = self.current_position.to_samples_mapped(
&self.tempo_map, self.project_config.sample_rate,
self.time_signature_numerator as u32,
);
self.record_automation_point(i, crate::automation::AutomationTarget::Volume, sample_pos, vol_val);
}
}
track_header::Message::PanChanged(pan) => {
track.pan = if pan.abs() < 0.02 { 0.0 } else { pan };
if let Some(ref engine) = self.engine {
engine.send(EngineCommand::SetBusPan {
bus_name: track.bus_name.clone(),
pan: track.pan,
});
}
let should_record = self.transport == TransportState::Playing && track.automation_mode.writes();
let pan_val = track.pan;
self.mark_dirty();
if should_record {
let sample_pos = self.current_position.to_samples_mapped(
&self.tempo_map, self.project_config.sample_rate,
self.time_signature_numerator as u32,
);
self.record_automation_point(i, crate::automation::AutomationTarget::Pan, sample_pos, pan_val);
}
}
track_header::Message::Delete => {
let removed = self.tracks.remove(i);
for region in &removed.regions {
self.waveform_cache.remove(&region.id);
}
if let Some(ref engine) = self.engine {
engine.send(EngineCommand::RemoveBus {
name: removed.bus_name.clone(),
});
}
self.history.push(EditCommand::DeleteTrack {
index: i,
track: removed,
});
self.mark_dirty();
if self.selected_track == Some(i) {
self.selected_track = None;
} else if let Some(sel) = self.selected_track {
if sel > i {
self.selected_track = Some(sel - 1);
}
}
}
track_header::Message::Select => {
self.selected_track = Some(i);
for (idx, t) in self.tracks.iter_mut().enumerate() {
t.selected = idx == i;
}
}
track_header::Message::FreezeToggled => {
return self.update(Message::FreezeTrack(i));
}
}
}
}
Message::SetTrackColor(i, color) => {
if let Some(track) = self.tracks.get_mut(i) {
track.color = color;
self.mark_dirty();
}
}
Message::SetMonitorMode(i, mode) => {
if let Some(track) = self.tracks.get_mut(i) {
track.monitor_mode = mode;
self.mark_dirty();
}
}
_ => {}
}
Task::none()
}
}