audio-oxide/au-o2-gui/src/gui/new_project.rs

151 lines
4.6 KiB
Rust

use crate::config::ProjectConfig;
use crate::entry::Message;
use cpal::traits::{DeviceTrait, HostTrait};
use iced::widget::{button, column, container, pick_list, row, slider, text, text_input};
use iced::{Alignment, Element};
use std::collections::BTreeSet;
#[derive(Debug, Clone)]
pub struct State {
pub config: ProjectConfig,
pub available_output_devices: BTreeSet<String>,
pub available_input_devices: BTreeSet<String>,
}
impl Default for State {
fn default() -> Self {
let host = cpal::default_host();
let output_devices = host
.output_devices()
.ok()
.into_iter()
.flatten()
.filter_map(|d| d.name().ok())
.collect();
let input_devices = host
.input_devices()
.ok()
.into_iter()
.flatten()
.filter_map(|d| d.name().ok())
.collect();
Self {
config: ProjectConfig {
name: "New Project".to_string(),
sample_rate: 48000,
output_buffer_size: 512,
input_buffer_size: 512,
audio_device: "Default".to_string(),
audio_input_device: "Default".to_string(),
auto_oversample: true,
auto_undersample: true,
tempo: 120.0,
time_signature_numerator: 4,
time_signature_denominator: 4,
tracks: Vec::new(),
},
available_output_devices: output_devices,
available_input_devices: input_devices,
}
}
}
pub fn view(state: &State) -> Element<'static, Message> {
let config = &state.config;
let sample_rates = vec![44100, 48000, 96000];
let buffer_sizes = vec![256, 512, 1024];
let output_devices: Vec<String> = state.available_output_devices.iter().cloned().collect();
let input_devices: Vec<String> = state.available_input_devices.iter().cloned().collect();
let controls = column![
row![
text("Project Name:").width(150),
text_input("My Awesome Track", &config.name).on_input(Message::ProjectNameChanged)
]
.spacing(10),
row![
text("Sample Rate:").width(150),
pick_list(
sample_rates,
Some(config.sample_rate),
Message::SampleRateSelected
)
]
.spacing(10),
row![
text("Output Buffer:").width(150),
pick_list(
buffer_sizes.clone(),
Some(config.output_buffer_size),
Message::OutputBufferSizeSelected
)
]
.spacing(10),
row![
text("Input Buffer:").width(150),
pick_list(
buffer_sizes,
Some(config.input_buffer_size),
Message::InputBufferSizeSelected
)
]
.spacing(10),
row![
text("Output Device:").width(150),
pick_list(
output_devices,
Some(config.audio_device.clone()),
Message::AudioDeviceSelected
)
]
.spacing(10),
row![
text("Input Device:").width(150),
pick_list(
input_devices,
Some(config.audio_input_device.clone()),
Message::InputDeviceSelected
)
]
.spacing(10),
row![
text("Time Signature:").width(150),
text_input("4", &config.time_signature_numerator.to_string())
.on_input(Message::TimeSignatureNumeratorChanged)
.width(50),
text("/").width(20).align_x(Alignment::Center),
text_input("4", &config.time_signature_denominator.to_string())
.on_input(Message::TimeSignatureDenominatorChanged)
.width(50),
]
.spacing(10)
.align_y(Alignment::Center),
row![
text("Tempo (BPM):").width(150),
slider(40.0..=240.0, config.tempo, Message::TempoChanged).step(0.1),
text(format!("{:.1}", config.tempo))
]
.spacing(10),
container(row![
button("Time Utility").on_press(Message::ViewTimeUtility)
])
.align_x(Alignment::End),
]
.spacing(10);
column![
text("Create New Project").size(30),
controls,
row![
button("Create Project").on_press(Message::CreateProject),
button("Cancel").on_press(Message::ViewRecentProjects)
]
.spacing(10)
]
.spacing(20)
.align_x(Alignment::Center)
.into()
}