Skip to content

Commit

Permalink
Improve Output Selectrion
Browse files Browse the repository at this point in the history
  • Loading branch information
PolyMeilex committed Dec 2, 2020
1 parent d8dd196 commit 8db880e
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 66 deletions.
21 changes: 16 additions & 5 deletions src/output_manager/midi_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,21 @@ impl MidiBackend {
pub fn get_outputs(&self) -> Vec<OutputDescriptor> {
let mut outs = Vec::new();
let ports = self.midi_out.ports();
for p in ports {
for (id, p) in ports.into_iter().enumerate() {
let name = match self.midi_out.port_name(&p).ok() {
Some(name) => name,
None => String::from("Unknown"),
};
outs.push(OutputDescriptor::MidiOut(MidiPortInfo { port: p, name }))
outs.push(OutputDescriptor::MidiOut(MidiPortInfo {
id,
port: p,
name,
}))
}
outs
}

pub fn new_output_connection(port: MidiPortInfo) -> Option<MidiOutputConnection> {
pub fn new_output_connection(port: &MidiPortInfo) -> Option<MidiOutputConnection> {
let midi_out = MidiOutput::new("midi_out_conn").ok();

if let Some(midi_out) = midi_out {
Expand All @@ -47,8 +51,15 @@ impl OutputConnection for MidiOutputConnection {

#[derive(Clone)]
pub struct MidiPortInfo {
pub port: MidiOutputPort,
pub name: String,
id: usize,
port: MidiOutputPort,
name: String,
}

impl PartialEq for MidiPortInfo {
fn eq(&self, other: &Self) -> bool {
self.id == other.id && self.name == other.name
}
}

impl std::fmt::Display for MidiPortInfo {
Expand Down
37 changes: 21 additions & 16 deletions src/output_manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::{
path::Path,
};

#[derive(Debug, Clone)]
#[derive(Debug, Clone, PartialEq)]
pub enum OutputDescriptor {
Synth,
MidiOut(MidiPortInfo),
Expand Down Expand Up @@ -38,7 +38,9 @@ pub struct OutputManager {
synth_backend: Option<SynthBackend>,
midi_backend: Option<MidiBackend>,

output_connection: Box<dyn OutputConnection>,
output_connection: (OutputDescriptor, Box<dyn OutputConnection>),

pub selected_output_id: Option<usize>,
}

impl OutputManager {
Expand All @@ -62,7 +64,8 @@ impl OutputManager {
synth_backend,
midi_backend,

output_connection: Box::new(DummyOutput {}),
output_connection: (OutputDescriptor::DummyOutput, Box::new(DummyOutput {})),
selected_output_id: None,
}
}

Expand All @@ -82,28 +85,30 @@ impl OutputManager {
}

pub fn connect(&mut self, desc: OutputDescriptor) {
match desc {
OutputDescriptor::Synth => {
if let Some(ref mut synth) = self.synth_backend {
self.output_connection = Box::new(synth.new_output_connection());
if desc != self.output_connection.0 {
match desc {
OutputDescriptor::Synth => {
if let Some(ref mut synth) = self.synth_backend {
self.output_connection = (desc, Box::new(synth.new_output_connection()));
}
}
}
OutputDescriptor::MidiOut(info) => {
if let Some(conn) = MidiBackend::new_output_connection(info) {
self.output_connection = Box::new(conn);
OutputDescriptor::MidiOut(ref info) => {
if let Some(conn) = MidiBackend::new_output_connection(info) {
self.output_connection = (desc, Box::new(conn));
}
}
OutputDescriptor::DummyOutput => {
self.output_connection = (desc, Box::new(DummyOutput {}));
}
}
OutputDescriptor::DummyOutput => {
self.output_connection = Box::new(DummyOutput {});
}
}
}

pub fn note_on(&mut self, ch: u8, key: u8, vel: u8) {
self.output_connection.note_on(ch, key, vel);
self.output_connection.1.note_on(ch, key, vel);
}

pub fn note_off(&mut self, ch: u8, key: u8) {
self.output_connection.note_off(ch, key);
self.output_connection.1.note_off(ch, key);
}
}
75 changes: 45 additions & 30 deletions src/scene/menu_scene/iced_menu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,22 @@ pub enum Message {

OutputsUpdated(Vec<OutputDescriptor>),

MainMenuDone(lib_midi::Midi, OutputDescriptor),
MainMenuDone(lib_midi::Midi, usize, OutputDescriptor),
}

impl IcedMenu {
pub fn new(midi_file: Option<lib_midi::Midi>, outputs: Vec<OutputDescriptor>) -> Self {
pub fn new(
midi_file: Option<lib_midi::Midi>,
outputs: Vec<OutputDescriptor>,
out_id: Option<usize>,
) -> Self {
let mut carousel = Carousel::new();
carousel.update(outputs);

if let Some(id) = out_id {
carousel.id = id;
}

Self {
midi_file,

Expand Down Expand Up @@ -90,18 +98,20 @@ impl Program for IcedMenu {
}

Message::PlayPressed => {
// self.output_manager
// .borrow_mut()
// .connect(self.carousel.get_item().clone());

if self.midi_file.is_some() {
async fn play(midi: lib_midi::Midi, out: OutputDescriptor) -> Message {
Message::MainMenuDone(midi, out)
async fn play(
midi: lib_midi::Midi,
id: usize,
out: OutputDescriptor,
) -> Message {
Message::MainMenuDone(midi, id, out)
}

if self.midi_file.is_some() {
if let Some(midi) = std::mem::replace(&mut self.midi_file, None) {
return Command::from(play(midi, self.carousel.get_item().clone()));
if let Some(port) = self.carousel.get_item() {
return Command::from(play(midi, self.carousel.id, port.clone()));
}
}
}
}
Expand All @@ -111,7 +121,7 @@ impl Program for IcedMenu {
self.carousel.update(outs);
}

Message::MainMenuDone(_, _) => {}
Message::MainMenuDone(_, _, _) => {}
}

Command::none()
Expand All @@ -132,7 +142,11 @@ impl Program for IcedMenu {
.on_press(Message::FileSelectPressed),
);

let item = self.carousel.get_item().to_string();
let item = self
.carousel
.get_item()
.map(|o| o.to_string())
.unwrap_or("Disconected".to_string());

let text = Text::new(item)
.color(Color::WHITE)
Expand Down Expand Up @@ -203,24 +217,25 @@ impl Program for IcedMenu {
};

let footer: Element<_, _> = {
let content: Element<Self::Message, Self::Renderer> = if self.midi_file.is_some() {
let btn = NeoBtn::new(
&mut self.play_button,
Text::new("Play")
.size(30)
.horizontal_alignment(HorizontalAlignment::Center)
.vertical_alignment(VerticalAlignment::Center)
.color(Color::WHITE),
)
.min_height(50)
.height(Length::Fill)
.width(Length::Units(150))
.on_press(Message::PlayPressed);
let content: Element<Self::Message, Self::Renderer> =
if self.midi_file.is_some() && self.carousel.get_item().is_some() {
let btn = NeoBtn::new(
&mut self.play_button,
Text::new("Play")
.size(30)
.horizontal_alignment(HorizontalAlignment::Center)
.vertical_alignment(VerticalAlignment::Center)
.color(Color::WHITE),
)
.min_height(50)
.height(Length::Fill)
.width(Length::Units(150))
.on_press(Message::PlayPressed);

btn.into()
} else {
Row::new().into()
};
btn.into()
} else {
Row::new().into()
};

let footer = Container::new(content)
.padding(10)
Expand Down Expand Up @@ -272,8 +287,8 @@ impl Carousel {
}
}

fn get_item(&self) -> &OutputDescriptor {
&self.outputs[self.id]
fn get_item(&self) -> Option<&OutputDescriptor> {
self.outputs.get(self.id)
}
}

Expand Down
38 changes: 23 additions & 15 deletions src/scene/menu_scene/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ impl MenuScene {
let menu = IcedMenu::new(
std::mem::replace(&mut state.midi_file, None),
state.output_manager.get_outputs(),
state.output_manager.selected_output_id,
);
let iced_state = iced_native::program::State::new(
menu,
Expand Down Expand Up @@ -119,22 +120,27 @@ impl Scene for MenuScene {
self.iced_state.queue_event(event);
}

match &event {
winit::event::WindowEvent::KeyboardInput { input, .. } => match input.virtual_keycode {
Some(winit::event::VirtualKeyCode::Return) => {
if let winit::event::ElementState::Released = input.state {
self.iced_state
.queue_message(iced_menu::Message::PlayPressed)
}
}
Some(winit::event::VirtualKeyCode::Escape) => {
if let winit::event::ElementState::Released = input.state {
return SceneEvent::GoBack;
if let winit::event::WindowEvent::KeyboardInput { input, .. } = &event {
if let winit::event::ElementState::Released = input.state {
if let Some(key) = input.virtual_keycode {
match key {
winit::event::VirtualKeyCode::Space => self
.iced_state
.queue_message(iced_menu::Message::FileSelectPressed),
winit::event::VirtualKeyCode::Left => self
.iced_state
.queue_message(iced_menu::Message::PrevPressed),
winit::event::VirtualKeyCode::Right => self
.iced_state
.queue_message(iced_menu::Message::NextPressed),
winit::event::VirtualKeyCode::Return => self
.iced_state
.queue_message(iced_menu::Message::PlayPressed),
winit::event::VirtualKeyCode::Escape => return SceneEvent::GoBack,
_ => {}
}
}
_ => {}
},
_ => {}
}
}

SceneEvent::None
Expand All @@ -158,8 +164,10 @@ impl Scene for MenuScene {
let event = crate::block_on(async { f.await });

match event {
iced_menu::Message::MainMenuDone(midi, out) => {
iced_menu::Message::MainMenuDone(midi, id, out) => {
self.main_state.midi_file = Some(midi);

self.main_state.output_manager.selected_output_id = Some(id);
self.main_state.output_manager.connect(out);

return SceneEvent::MainMenu(Event::Play);
Expand Down

0 comments on commit 8db880e

Please sign in to comment.