Split UI drawing code out of main update code
This commit is contained in:
parent
51e0893c04
commit
3862080cb1
@ -216,7 +216,7 @@ impl AudioThread {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
AudioMessage::SetVolume(vol) => self.sl.set_global_volume(*vol / 100.0)
|
AudioMessage::SetVolume(vol) => self.sl.set_global_volume(*vol / 100.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use eframe::{
|
use eframe::{
|
||||||
egui::{self, KeyboardShortcut, Modifiers, Sense, TextureOptions, Ui, Widget, Key},
|
egui::{self, Key, KeyboardShortcut, Modifiers, Sense, TextureOptions, Ui, Widget},
|
||||||
epaint::{vec2, Pos2, Rect, TextureHandle},
|
epaint::{vec2, Pos2, Rect, TextureHandle},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -117,10 +117,7 @@ impl Widget for &mut Frontpanel<'_> {
|
|||||||
);
|
);
|
||||||
let led_textures =
|
let led_textures =
|
||||||
led::Textures::new(self.textures.led_on.clone(), self.textures.led_off.clone());
|
led::Textures::new(self.textures.led_on.clone(), self.textures.led_off.clone());
|
||||||
let resp = ui.allocate_response(
|
let resp = ui.allocate_response(vec2(800.0, 333.0), Sense::click());
|
||||||
vec2(800.0, 333.0),
|
|
||||||
Sense::click(),
|
|
||||||
);
|
|
||||||
resp.request_focus();
|
resp.request_focus();
|
||||||
let fp_rect = resp.rect;
|
let fp_rect = resp.rect;
|
||||||
ui.allocate_ui_at_rect(fp_rect, |ui| {
|
ui.allocate_ui_at_rect(fp_rect, |ui| {
|
||||||
@ -176,7 +173,11 @@ impl Widget for &mut Frontpanel<'_> {
|
|||||||
};
|
};
|
||||||
let shortcut = KeyboardShortcut::new(mods, key);
|
let shortcut = KeyboardShortcut::new(mods, key);
|
||||||
if ui
|
if ui
|
||||||
.add(switch::ToggleSwitch::new(&mut sw_state, &sw_textures, Some(shortcut)))
|
.add(switch::ToggleSwitch::new(
|
||||||
|
&mut sw_state,
|
||||||
|
&sw_textures,
|
||||||
|
Some(shortcut),
|
||||||
|
))
|
||||||
.changed()
|
.changed()
|
||||||
{
|
{
|
||||||
self.state.ad_sws =
|
self.state.ad_sws =
|
||||||
@ -207,7 +208,12 @@ impl Widget for &mut Frontpanel<'_> {
|
|||||||
let up_shortcut = KeyboardShortcut::new(Modifiers::NONE, up_key);
|
let up_shortcut = KeyboardShortcut::new(Modifiers::NONE, up_key);
|
||||||
let down_shortcut = KeyboardShortcut::new(Modifiers::NONE, down_key);
|
let down_shortcut = KeyboardShortcut::new(Modifiers::NONE, down_key);
|
||||||
if ui
|
if ui
|
||||||
.add(switch::ThreePosSwitch::new(state, &sw_textures, Some(up_shortcut), Some(down_shortcut)))
|
.add(switch::ThreePosSwitch::new(
|
||||||
|
state,
|
||||||
|
&sw_textures,
|
||||||
|
Some(up_shortcut),
|
||||||
|
Some(down_shortcut),
|
||||||
|
))
|
||||||
.changed()
|
.changed()
|
||||||
{
|
{
|
||||||
let sw = match i {
|
let sw = match i {
|
||||||
|
@ -59,8 +59,18 @@ pub struct ThreePosSwitch<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ThreePosSwitch<'a> {
|
impl<'a> ThreePosSwitch<'a> {
|
||||||
pub fn new(state: &'a mut SwitchState, textures: &'a Textures, up_shortcut: Option<KeyboardShortcut>, down_shortcut: Option<KeyboardShortcut>) -> Self {
|
pub fn new(
|
||||||
Self { state, textures, up_shortcut, down_shortcut }
|
state: &'a mut SwitchState,
|
||||||
|
textures: &'a Textures,
|
||||||
|
up_shortcut: Option<KeyboardShortcut>,
|
||||||
|
down_shortcut: Option<KeyboardShortcut>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
state,
|
||||||
|
textures,
|
||||||
|
up_shortcut,
|
||||||
|
down_shortcut,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,16 +84,24 @@ impl Widget for ThreePosSwitch<'_> {
|
|||||||
NULL_TINT,
|
NULL_TINT,
|
||||||
);
|
);
|
||||||
let up_shortcut_pressed = self.up_shortcut.map_or(false, |shortcut| {
|
let up_shortcut_pressed = self.up_shortcut.map_or(false, |shortcut| {
|
||||||
ui.input_mut(|input| input.key_pressed(shortcut.logical_key) && shortcut.modifiers == input.modifiers)
|
ui.input_mut(|input| {
|
||||||
|
input.key_pressed(shortcut.logical_key) && shortcut.modifiers == input.modifiers
|
||||||
|
})
|
||||||
});
|
});
|
||||||
let down_shortcut_pressed = self.down_shortcut.map_or(false, |shortcut| {
|
let down_shortcut_pressed = self.down_shortcut.map_or(false, |shortcut| {
|
||||||
ui.input_mut(|input| input.key_pressed(shortcut.logical_key) && shortcut.modifiers == input.modifiers)
|
ui.input_mut(|input| {
|
||||||
|
input.key_pressed(shortcut.logical_key) && shortcut.modifiers == input.modifiers
|
||||||
|
})
|
||||||
});
|
});
|
||||||
let up_shortcut_released = self.up_shortcut.map_or(false, |shortcut| {
|
let up_shortcut_released = self.up_shortcut.map_or(false, |shortcut| {
|
||||||
ui.input_mut(|input| input.key_released(shortcut.logical_key) && shortcut.modifiers == input.modifiers)
|
ui.input_mut(|input| {
|
||||||
|
input.key_released(shortcut.logical_key) && shortcut.modifiers == input.modifiers
|
||||||
|
})
|
||||||
});
|
});
|
||||||
let down_shortcut_released = self.down_shortcut.map_or(false, |shortcut| {
|
let down_shortcut_released = self.down_shortcut.map_or(false, |shortcut| {
|
||||||
ui.input_mut(|input| input.key_released(shortcut.logical_key) && shortcut.modifiers == input.modifiers)
|
ui.input_mut(|input| {
|
||||||
|
input.key_released(shortcut.logical_key) && shortcut.modifiers == input.modifiers
|
||||||
|
})
|
||||||
});
|
});
|
||||||
let old_state = *self.state;
|
let old_state = *self.state;
|
||||||
if resp.dragged() {
|
if resp.dragged() {
|
||||||
@ -101,7 +119,10 @@ impl Widget for ThreePosSwitch<'_> {
|
|||||||
} else if resp.drag_released() || up_shortcut_released || down_shortcut_released {
|
} else if resp.drag_released() || up_shortcut_released || down_shortcut_released {
|
||||||
*self.state = SwitchState::Neut;
|
*self.state = SwitchState::Neut;
|
||||||
}
|
}
|
||||||
if *self.state != SwitchState::Neut && !resp.dragged() && ui.input(|input| input.keys_down.is_empty()) {
|
if *self.state != SwitchState::Neut
|
||||||
|
&& !resp.dragged()
|
||||||
|
&& ui.input(|input| input.keys_down.is_empty())
|
||||||
|
{
|
||||||
*self.state = SwitchState::Neut;
|
*self.state = SwitchState::Neut;
|
||||||
}
|
}
|
||||||
if *self.state != old_state {
|
if *self.state != old_state {
|
||||||
|
280
src/main.rs
280
src/main.rs
@ -9,7 +9,7 @@ use std::sync::mpsc::Sender;
|
|||||||
use audio::{AudioMessage, AudioThread};
|
use audio::{AudioMessage, AudioThread};
|
||||||
use cpu::{MemCycle, Status, I8080};
|
use cpu::{MemCycle, Status, I8080};
|
||||||
use eframe::{
|
use eframe::{
|
||||||
egui::{self, menu, Button, Slider},
|
egui::{self, menu, Button, Slider, Ui},
|
||||||
NativeOptions,
|
NativeOptions,
|
||||||
};
|
};
|
||||||
use egui_modal::Modal;
|
use egui_modal::Modal;
|
||||||
@ -66,14 +66,20 @@ struct AltairEmulator {
|
|||||||
impl AltairEmulator {
|
impl AltairEmulator {
|
||||||
fn new(cc: &eframe::CreationContext<'_>, audio_tx: Sender<AudioMessage>) -> Self {
|
fn new(cc: &eframe::CreationContext<'_>, audio_tx: Sender<AudioMessage>) -> Self {
|
||||||
let options = if cc.storage.unwrap().get_string("options").is_none() {
|
let options = if cc.storage.unwrap().get_string("options").is_none() {
|
||||||
Options { mute: false, fan_enabled: true, volume: 1.0 }
|
Options {
|
||||||
|
mute: false,
|
||||||
|
fan_enabled: true,
|
||||||
|
volume: 1.0,
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
eframe::get_value(cc.storage.unwrap(), "options").unwrap()
|
eframe::get_value(cc.storage.unwrap(), "options").unwrap()
|
||||||
};
|
};
|
||||||
if options.mute {
|
if options.mute {
|
||||||
audio_tx.send(AudioMessage::SetVolume(0.0)).unwrap();
|
audio_tx.send(AudioMessage::SetVolume(0.0)).unwrap();
|
||||||
} else {
|
} else {
|
||||||
audio_tx.send(AudioMessage::SetVolume(options.volume)).unwrap();
|
audio_tx
|
||||||
|
.send(AudioMessage::SetVolume(options.volume))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
let mut mem = [0; 65536];
|
let mut mem = [0; 65536];
|
||||||
let cpu = I8080::new();
|
let cpu = I8080::new();
|
||||||
@ -163,6 +169,132 @@ impl AltairEmulator {
|
|||||||
self.cpu.finish_m_cycle(data);
|
self.cpu.finish_m_cycle(data);
|
||||||
self.update_fp();
|
self.update_fp();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn show_menubar(&mut self, ui: &mut Ui) {
|
||||||
|
menu::bar(ui, |ui| {
|
||||||
|
menu::menu_button(ui, "Edit", |ui| {
|
||||||
|
if ui
|
||||||
|
.add_enabled(self.option_window.is_none(), Button::new("Options"))
|
||||||
|
.clicked()
|
||||||
|
{
|
||||||
|
self.option_window = Some(OptionWindow::new(ui.ctx(), self.options));
|
||||||
|
ui.close_menu();
|
||||||
|
}
|
||||||
|
if ui.button("Load binary file").clicked() {
|
||||||
|
let ihex_exts = ["hex", "mcs", "int", "ihex", "ihe", "ihx"];
|
||||||
|
let file = FileDialog::new()
|
||||||
|
.add_filter(
|
||||||
|
"Binary files",
|
||||||
|
&["bin", "img", "hex", "mcs", "int", "ihex", "ihe", "ihx"],
|
||||||
|
)
|
||||||
|
.add_filter("All files", &["*"])
|
||||||
|
.pick_file();
|
||||||
|
if let Some(file) = file {
|
||||||
|
if file
|
||||||
|
.extension()
|
||||||
|
.map_or(false, |ext| ihex_exts.contains(&ext.to_str().unwrap_or("")))
|
||||||
|
{
|
||||||
|
let data = std::fs::read_to_string(file).unwrap();
|
||||||
|
for record in ihex::Reader::new(&data) {
|
||||||
|
let record = record.unwrap();
|
||||||
|
match record {
|
||||||
|
ihex::Record::Data { offset, value } => {
|
||||||
|
for (i, &byte) in value.iter().enumerate() {
|
||||||
|
self.mem[offset as usize + i] = byte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ihex::Record::StartLinearAddress(_) => todo!(),
|
||||||
|
_ => unimplemented!(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Raw binary
|
||||||
|
todo!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn show_frontpanel(&mut self, ui: &mut Ui) {
|
||||||
|
let mut fp = Frontpanel::new(&self.textures, &mut self.fp_state);
|
||||||
|
ui.add(&mut fp);
|
||||||
|
let interaction = fp.interaction();
|
||||||
|
if let Some(interaction) = interaction {
|
||||||
|
self.audio_tx.send(AudioMessage::PlaySwitchClick).unwrap();
|
||||||
|
match interaction {
|
||||||
|
FrontpanelInteraction::ActionSwChanged(sw, state) => {
|
||||||
|
if self.fp_state.power() {
|
||||||
|
match sw {
|
||||||
|
frontpanel::ActionSwitch::RunStop => {
|
||||||
|
if state == SwitchState::Up {
|
||||||
|
self.running = false;
|
||||||
|
} else if state == SwitchState::Down {
|
||||||
|
self.running = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frontpanel::ActionSwitch::SingleStep => {
|
||||||
|
if state == SwitchState::Up {
|
||||||
|
self.run_cpu_cycle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frontpanel::ActionSwitch::Examine => {
|
||||||
|
if state == SwitchState::Up {
|
||||||
|
// Assume M1
|
||||||
|
self.cpu.finish_m_cycle(0xC3); // JMP
|
||||||
|
self.cpu.finish_m_cycle(self.fp_state.ad_sws() as u8);
|
||||||
|
self.cpu.finish_m_cycle((self.fp_state.ad_sws() >> 8) as u8);
|
||||||
|
self.update_fp();
|
||||||
|
} else if state == SwitchState::Down {
|
||||||
|
// Assume M1
|
||||||
|
self.cpu.finish_m_cycle(0x0); // NOP
|
||||||
|
self.update_fp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frontpanel::ActionSwitch::Deposit => {
|
||||||
|
if state == SwitchState::Up {
|
||||||
|
// Assume M1
|
||||||
|
self.mem[self.cpu.get_mem_cycle().address() as usize] =
|
||||||
|
self.fp_state.ad_sws() as u8;
|
||||||
|
self.update_fp();
|
||||||
|
} else if state == SwitchState::Down {
|
||||||
|
// Assume M1
|
||||||
|
self.cpu.finish_m_cycle(0x0); // NOP
|
||||||
|
self.mem[self.cpu.get_mem_cycle().address() as usize] =
|
||||||
|
self.fp_state.ad_sws() as u8;
|
||||||
|
self.update_fp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frontpanel::ActionSwitch::Reset => {
|
||||||
|
if state == SwitchState::Up {
|
||||||
|
self.cpu.reset();
|
||||||
|
self.update_fp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frontpanel::ActionSwitch::Protect => (),
|
||||||
|
frontpanel::ActionSwitch::Aux1 => (),
|
||||||
|
frontpanel::ActionSwitch::Aux2 => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FrontpanelInteraction::AdChanged(_) => (),
|
||||||
|
FrontpanelInteraction::PowerChanged(pwr) => {
|
||||||
|
if pwr {
|
||||||
|
self.audio_tx.send(AudioMessage::FanOn).unwrap();
|
||||||
|
self.cpu = I8080::new();
|
||||||
|
self.update_fp();
|
||||||
|
} else {
|
||||||
|
self.audio_tx.send(AudioMessage::FanOff).unwrap();
|
||||||
|
self.running = false;
|
||||||
|
self.fp_state.set_status(Status::empty());
|
||||||
|
self.fp_state.set_addr(0);
|
||||||
|
self.fp_state.set_data(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl eframe::App for AltairEmulator {
|
impl eframe::App for AltairEmulator {
|
||||||
@ -171,137 +303,11 @@ impl eframe::App for AltairEmulator {
|
|||||||
}
|
}
|
||||||
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||||
ctx.set_pixels_per_point(1.0);
|
ctx.set_pixels_per_point(1.0);
|
||||||
// frame.set_window_size((800.0, 333.0).into());
|
egui::TopBottomPanel::top("menu").show(ctx, |ui| self.show_menubar(ui));
|
||||||
let mut disable_fp_sws = self.option_window.is_some();
|
egui::CentralPanel::default().show(ctx, |ui| self.show_frontpanel(ui));
|
||||||
egui::TopBottomPanel::top("menu").show(ctx, |ui| {
|
if self.running {
|
||||||
menu::bar(ui, |ui| {
|
self.run_cpu_cycle();
|
||||||
menu::menu_button(ui, "Edit", |ui| {
|
}
|
||||||
disable_fp_sws = true;
|
|
||||||
if ui
|
|
||||||
.add_enabled(self.option_window.is_none(), Button::new("Options"))
|
|
||||||
.clicked()
|
|
||||||
{
|
|
||||||
self.option_window = Some(OptionWindow::new(ctx, self.options));
|
|
||||||
ui.close_menu();
|
|
||||||
}
|
|
||||||
if ui.button("Load binary file").clicked() {
|
|
||||||
let ihex_exts = ["hex", "mcs", "int", "ihex", "ihe", "ihx"];
|
|
||||||
let file = FileDialog::new()
|
|
||||||
.add_filter(
|
|
||||||
"Binary files",
|
|
||||||
&["bin", "img", "hex", "mcs", "int", "ihex", "ihe", "ihx"],
|
|
||||||
)
|
|
||||||
.add_filter("All files", &["*"])
|
|
||||||
.pick_file();
|
|
||||||
if let Some(file) = file {
|
|
||||||
if file.extension().map_or(false, |ext| {
|
|
||||||
ihex_exts.contains(&ext.to_str().unwrap_or(""))
|
|
||||||
}) {
|
|
||||||
let data = std::fs::read_to_string(file).unwrap();
|
|
||||||
for record in ihex::Reader::new(&data) {
|
|
||||||
let record = record.unwrap();
|
|
||||||
match record {
|
|
||||||
ihex::Record::Data { offset, value } => {
|
|
||||||
for (i, &byte) in value.iter().enumerate() {
|
|
||||||
self.mem[offset as usize + i] = byte;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ihex::Record::StartLinearAddress(_) => todo!(),
|
|
||||||
_ => unimplemented!(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Raw binary
|
|
||||||
todo!();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
egui::CentralPanel::default().show(ctx, |ui| {
|
|
||||||
let mut fp = Frontpanel::new(&self.textures, &mut self.fp_state);
|
|
||||||
ui.add(&mut fp);
|
|
||||||
let interaction = fp.interaction();
|
|
||||||
if let Some(interaction) = interaction {
|
|
||||||
self.audio_tx.send(AudioMessage::PlaySwitchClick).unwrap();
|
|
||||||
match interaction {
|
|
||||||
FrontpanelInteraction::ActionSwChanged(sw, state) => {
|
|
||||||
if self.fp_state.power() {
|
|
||||||
match sw {
|
|
||||||
frontpanel::ActionSwitch::RunStop => {
|
|
||||||
if state == SwitchState::Up {
|
|
||||||
self.running = false;
|
|
||||||
} else if state == SwitchState::Down {
|
|
||||||
self.running = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
frontpanel::ActionSwitch::SingleStep => {
|
|
||||||
if state == SwitchState::Up {
|
|
||||||
self.run_cpu_cycle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
frontpanel::ActionSwitch::Examine => {
|
|
||||||
if state == SwitchState::Up {
|
|
||||||
// Assume M1
|
|
||||||
self.cpu.finish_m_cycle(0xC3); // JMP
|
|
||||||
self.cpu.finish_m_cycle(self.fp_state.ad_sws() as u8);
|
|
||||||
self.cpu
|
|
||||||
.finish_m_cycle((self.fp_state.ad_sws() >> 8) as u8);
|
|
||||||
self.update_fp();
|
|
||||||
} else if state == SwitchState::Down {
|
|
||||||
// Assume M1
|
|
||||||
self.cpu.finish_m_cycle(0x0); // NOP
|
|
||||||
self.update_fp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
frontpanel::ActionSwitch::Deposit => {
|
|
||||||
if state == SwitchState::Up {
|
|
||||||
// Assume M1
|
|
||||||
self.mem[self.cpu.get_mem_cycle().address() as usize] =
|
|
||||||
self.fp_state.ad_sws() as u8;
|
|
||||||
self.update_fp();
|
|
||||||
} else if state == SwitchState::Down {
|
|
||||||
// Assume M1
|
|
||||||
self.cpu.finish_m_cycle(0x0); // NOP
|
|
||||||
self.mem[self.cpu.get_mem_cycle().address() as usize] =
|
|
||||||
self.fp_state.ad_sws() as u8;
|
|
||||||
self.update_fp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
frontpanel::ActionSwitch::Reset => {
|
|
||||||
if state == SwitchState::Up {
|
|
||||||
self.cpu.reset();
|
|
||||||
self.update_fp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
frontpanel::ActionSwitch::Protect => (),
|
|
||||||
frontpanel::ActionSwitch::Aux1 => (),
|
|
||||||
frontpanel::ActionSwitch::Aux2 => (),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
FrontpanelInteraction::AdChanged(_) => (),
|
|
||||||
FrontpanelInteraction::PowerChanged(pwr) => {
|
|
||||||
if pwr {
|
|
||||||
self.audio_tx.send(AudioMessage::FanOn).unwrap();
|
|
||||||
self.cpu = I8080::new();
|
|
||||||
self.update_fp();
|
|
||||||
} else {
|
|
||||||
self.audio_tx.send(AudioMessage::FanOff).unwrap();
|
|
||||||
self.running = false;
|
|
||||||
self.fp_state.set_status(Status::empty());
|
|
||||||
self.fp_state.set_addr(0);
|
|
||||||
self.fp_state.set_data(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if self.running {
|
|
||||||
self.run_cpu_cycle();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let old_fan_enabled = self.options.fan_enabled;
|
let old_fan_enabled = self.options.fan_enabled;
|
||||||
if let Some(option_window) = self.option_window.as_mut() {
|
if let Some(option_window) = self.option_window.as_mut() {
|
||||||
if option_window.draw(ctx, &mut self.options) {
|
if option_window.draw(ctx, &mut self.options) {
|
||||||
@ -310,13 +316,15 @@ impl eframe::App for AltairEmulator {
|
|||||||
if self.options.mute {
|
if self.options.mute {
|
||||||
self.audio_tx.send(AudioMessage::SetVolume(0.0)).unwrap();
|
self.audio_tx.send(AudioMessage::SetVolume(0.0)).unwrap();
|
||||||
} else {
|
} else {
|
||||||
self.audio_tx.send(AudioMessage::SetVolume(self.options.volume)).unwrap();
|
self.audio_tx
|
||||||
|
.send(AudioMessage::SetVolume(self.options.volume))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (old_fan_enabled != self.options.fan_enabled) && self.fp_state.power() {
|
if (old_fan_enabled != self.options.fan_enabled) && self.fp_state.power() {
|
||||||
if self.options.fan_enabled {
|
if self.options.fan_enabled {
|
||||||
self.audio_tx.send(AudioMessage::FanOn).unwrap();
|
self.audio_tx.send(AudioMessage::FanOn).unwrap();
|
||||||
} else {
|
} else {
|
||||||
self.audio_tx.send(AudioMessage::FanOff).unwrap();
|
self.audio_tx.send(AudioMessage::FanOff).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user