Skip to content
This repository has been archived by the owner on Feb 2, 2019. It is now read-only.

Commit

Permalink
{ui, backend}: add DurationEntry, fix fading check
Browse files Browse the repository at this point in the history
  • Loading branch information
eeeeeta committed Jun 15, 2017
1 parent 2b3e81d commit ed36fb1
Show file tree
Hide file tree
Showing 10 changed files with 139 additions and 10 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -5,3 +5,4 @@ target
.#*
*~
*#
.gdb_history
10 changes: 5 additions & 5 deletions sqa-backend/src/actions/fade.rs
Expand Up @@ -7,6 +7,7 @@ use errors::BackendResult;
use uuid::Uuid;
use std::time::Duration;
use std::default::Default;
use super::audio::db_lin;

#[derive(Serialize, Deserialize, Clone, Debug, Default)]
pub struct FadeParams {
Expand All @@ -31,7 +32,6 @@ impl EditableAction for Controller {
&self.params
}
fn set_params(&mut self, params: FadeParams, _: &mut Context) {
println!("pars: {:?}", params);
self.params = params;
}
}
Expand Down Expand Up @@ -66,8 +66,8 @@ impl ActionController for Controller {
err: "No target is specified.".into()
});
}
if self.params.fades.iter().fold(true, |acc, elem|
if elem.is_some() && !acc { true } else { acc }) {
if self.params.fade_master.is_none() && self.params.fades.iter().fold(true, |acc, elem|
if elem.is_some() && !acc { true } else { acc }){
ret.push(ParameterError {
name: "fades".into(),
err: "Nothing is being faded.".into()
Expand All @@ -84,7 +84,7 @@ impl ActionController for Controller {
};
if let Some(fade) = self.params.fade_master {
if let Some(sdr) = tgt.senders.get_mut(0) {
let mut fd = FadeDetails::new(sdr.volume().get(0), fade);
let mut fd = FadeDetails::new(sdr.volume().get(0), db_lin(fade));
fd.set_start_time(time);
let secs_component = self.params.dur.as_secs() * ::sqa_engine::ONE_SECOND_IN_NANOSECONDS;
let subsec_component = self.params.dur.subsec_nanos() as u64;
Expand All @@ -96,7 +96,7 @@ impl ActionController for Controller {
for (i, fade) in self.params.fades.iter().enumerate() {
if let Some(fade) = *fade {
if let Some(sdr) = tgt.senders.get_mut(i) {
let mut fd = FadeDetails::new(sdr.volume().get(0), fade);
let mut fd = FadeDetails::new(sdr.volume().get(0), db_lin(fade));
fd.set_start_time(time);
let secs_component = self.params.dur.as_secs() * ::sqa_engine::ONE_SECOND_IN_NANOSECONDS;
let subsec_component = self.params.dur.subsec_nanos() as u64;
Expand Down
1 change: 0 additions & 1 deletion sqa-backend/src/codec.rs
Expand Up @@ -159,7 +159,6 @@ impl UdpCodec for SqaWireCodec {
type In = RecvMessage;
type Out = SendMessage;
fn decode(&mut self, src: &SocketAddr, buf: &[u8]) -> ::std::io::Result<Self::In> {
println!("{:?}", buf);
let pkt = match decoder::decode(buf) {
Ok(pkt) => {
match pkt {
Expand Down
1 change: 0 additions & 1 deletion sqa-backend/src/state.rs
Expand Up @@ -117,7 +117,6 @@ impl ConnHandler for Context {
d.respond(ActionInfoRetrieved { uuid, res })?;
},
UpdateActionParams { uuid, params } => {
println!("uap: {:?}", params);
let res = do_with_ctx!(self, &uuid, |a: &mut Action| {
let ret = a.set_params(params, self).map_err(|e| e.to_string());
self.on_action_changed(d, a);
Expand Down
1 change: 1 addition & 0 deletions sqa-ui/src/actions/audio.rs
Expand Up @@ -9,6 +9,7 @@ use sqa_backend::mixer::MixerConf;
use sqa_backend::actions::{ActionParameters, PlaybackState};
use sqa_backend::actions::audio::AudioParams;

#[derive(Clone)]
pub enum AudioMessage {
Slider(usize, PatchedSliderMessage),
FileChanged
Expand Down
28 changes: 25 additions & 3 deletions sqa-ui/src/actions/fade.rs
@@ -1,7 +1,8 @@
use gtk::prelude::*;
use gtk::{Button, Widget};
use super::{ActionMessageInner, ActionInternalMessage, ActionMessage, OpaqueAction, UISender, ActionUI, UITemplate};
use widgets::{SliderBox, Faded, SliderMessage, FadedSliderMessage};
use std::time::Duration;
use widgets::{SliderBox, Faded, DurationEntry, DurationEntryMessage, SliderMessage, FadedSliderMessage};
use uuid::Uuid;
use std::cell::Cell;
use std::rc::Rc;
Expand All @@ -10,8 +11,10 @@ use sqa_backend::codec::Command;
use sqa_backend::actions::ActionParameters;
use sqa_backend::actions::fade::FadeParams;

#[derive(Clone)]
pub enum FadeMessage {
Slider(usize, FadedSliderMessage)
Slider(usize, FadedSliderMessage),
DurationModified(Duration)
}
impl SliderMessage<Faded> for FadeMessage {
type Message = ActionMessage;
Expand All @@ -23,11 +26,21 @@ impl SliderMessage<Faded> for FadeMessage {
(id, Fade(Slider(ch, data)))
}
}
impl DurationEntryMessage for FadeMessage {
type Message = ActionMessage;
type Identifier = Uuid;

fn on_payload(dur: Duration, id: Uuid) -> Self::Message {
use self::ActionMessageInner::*;
use self::FadeMessage::*;
(id, Fade(DurationModified(dur)))
}
}
pub struct FadeUI {
temp: UITemplate,
sel: Button,
params: FadeParams,
dur: DurationEntry,
sb: SliderBox<Faded, FadeMessage>,
selecting: Rc<Cell<bool>>,
actionlist: HashMap<Uuid, OpaqueAction>,
Expand All @@ -38,12 +51,14 @@ impl FadeUI {
let mut temp = UITemplate::new(uu, tx.clone());
let sb = SliderBox::new(0, 0, &tx, uu);
let params = Default::default();
let dur = DurationEntry::new();
let sel = Button::new_with_label("[choose...]");
let selecting = Rc::new(Cell::new(false));
let actionlist = HashMap::new();
temp.pwin.append_property("Target", &sel);
temp.pwin.append_property("Duration", &*dur);
temp.pwin.props_box.pack_start(&sb.grid, false, true, 5);
let mut ctx = FadeUI { temp, params, sb, sel, tx, selecting, actionlist };
let mut ctx = FadeUI { temp, params, sb, sel, tx, selecting, actionlist, dur };
ctx.bind();
ctx
}
Expand All @@ -52,6 +67,7 @@ impl FadeUI {
let ref tx = self.tx;
let ref selecting = self.selecting;
let uu = self.temp.uu;
self.dur.bind::<FadeMessage>(tx, uu);
self.sel.connect_clicked(clone!(tx, selecting; |slf| {
if selecting.get() {
tx.send_internal(ActionInternalMessage::CancelSelection);
Expand All @@ -77,6 +93,7 @@ impl FadeUI {
else {
self.sel.set_label("[choose...]");
}
self.dur.set(p.dur);
if p.fades.len() != self.sb.n_sliders() {
self.sb.grid.destroy();
self.sb = SliderBox::new(p.fades.len(), 0, &self.temp.tx, self.temp.uu);
Expand Down Expand Up @@ -116,6 +133,11 @@ impl ActionUI for FadeUI {
*v = val;
}
self.apply_changes();
},
DurationModified(dur) => {
self.params.dur = dur;
trace!("dur cb: new dur {:?}", dur);
self.apply_changes();
}
}
}
Expand Down
1 change: 1 addition & 0 deletions sqa-ui/src/actions/mod.rs
Expand Up @@ -23,6 +23,7 @@ pub enum ActionInternalMessage {
BeginSelection(Uuid),
CancelSelection
}
#[derive(Clone)]
pub enum ActionMessageInner {
Audio(audio::AudioMessage),
Fade(fade::FadeMessage),
Expand Down
103 changes: 103 additions & 0 deletions sqa-ui/src/widgets/duration.rs
@@ -0,0 +1,103 @@
use gtk::prelude::*;
use gtk::Entry;
use std::cell::Cell;
use std::time::Duration;
use std::ops::Deref;
use sync::{UISender, UIMessage};

pub trait DurationEntryMessage {
type Message: Into<UIMessage>;
type Identifier: Copy + 'static;

fn on_payload(dur: Duration, id: Self::Identifier) -> Self::Message;
}
pub struct DurationEntry {
dur: Cell<Duration>,
ent: Entry,
}
macro_rules! try_or_none {
($e:expr) => {
match $e {
Ok(x) => x,
Err(_) => return None
}
}
}
impl DurationEntry {
pub fn new() -> Self {
let dur = Cell::new(Default::default());
let ent = Entry::new();
Self { dur, ent }
}
pub fn bind<T: DurationEntryMessage>(&self, tx: &UISender, id: T::Identifier) {
let dc = &self.dur;
self.ent.connect_activate(clone!(tx, id, dc; |slf| {
trace!("duration entry activated");
if let Some(dur) = Self::parse(&slf.get_text().unwrap_or("".into())) {
dc.set(dur);
tx.send_internal(T::on_payload(dur, id));
trace!("new duration: {:?}", dur);
}
}));
self.ent.connect_focus_out_event(clone!(tx, id, dc; |slf, _| {
if let Some(dur) = Self::parse(&slf.get_text().unwrap_or("".into())) {
dc.set(dur);
tx.send_internal(T::on_payload(dur, id));
}
else {
trace!("resetting duration to {:?} because input was bad", dc.get());
slf.set_text(&Self::format(dc.get()));
}
Inhibit(false)
}));
}
pub fn format(dur: Duration) -> String {
let secs = dur.as_secs();
let hrs = secs / 3600;
let mins = (secs / 60).saturating_sub(60 * hrs);
let just_secs = secs.saturating_sub(60 * mins).saturating_sub(3600 * hrs);
let millis = (dur.subsec_nanos() as u64 / 1_000_000).saturating_sub(just_secs * 1000);
let hrs = if hrs > 0 {
format!("{:02}:", hrs)
}
else {
"".to_string()
};
trace!("format orig_secs {} h{} m{} s{} mi{}", secs, hrs, mins, just_secs, millis);
format!("{}{:02}:{:02}.{:03}", hrs, mins, just_secs, millis)
}
pub fn parse(st: &str) -> Option<Duration> {
let time_components = st.rsplit(":").collect::<Vec<_>>();
let (mut secs, mut nanos) = (0, 0);
if let Some(secs_and_millis) = time_components.get(0) {
let secs_and_millis = try_or_none!(secs_and_millis.parse::<f64>());
if !secs_and_millis.is_finite() {
return None;
}
let s = secs_and_millis.trunc();
let ms = (secs_and_millis - s) * 1000.0;
trace!("parse s&m {} s {} ms {}", secs_and_millis, s, ms);
secs += s as u64;
nanos += (ms as u32) * 1_000_000;
}
if let Some(mins) = time_components.get(1) {
secs += try_or_none!(mins.parse::<u64>()) * 60;
}
if let Some(hrs) = time_components.get(2) {
secs += try_or_none!(hrs.parse::<u64>()) * 3600;
}
Some(Duration::new(secs, nanos))
}
pub fn set(&mut self, dur: Duration) {
self.dur.set(dur);
self.ent.set_text(&Self::format(dur));
}
}

impl Deref for DurationEntry {
type Target = Entry;

fn deref(&self) -> &Entry {
&self.ent
}
}
1 change: 1 addition & 0 deletions sqa-ui/src/widgets/mixer.rs
Expand Up @@ -4,6 +4,7 @@ use glib::signal;
use sync::{UISender, UIMessage};
use std::marker::PhantomData;

#[derive(Clone)]
pub enum PatchedSliderMessage {
VolChanged(f32),
PatchChanged(usize)
Expand Down
2 changes: 2 additions & 0 deletions sqa-ui/src/widgets/mod.rs
@@ -1,7 +1,9 @@
mod prop;
mod entry;
mod mixer;
mod duration;

pub use self::prop::PropertyWindow;
pub use self::entry::FallibleEntry;
pub use self::mixer::{SliderBox, SliderMessage, PatchedSliderMessage, SliderDetail, FadedSliderMessage, FadedSliderDetail, Patched, Faded};
pub use self::duration::{DurationEntry, DurationEntryMessage};

0 comments on commit ed36fb1

Please sign in to comment.