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 { 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(®ion.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() } }