Skip to content

Commit

Permalink
detect volume changes
Browse files Browse the repository at this point in the history
  • Loading branch information
mdonoughe committed Feb 17, 2019
1 parent a5acdb9 commit 48731d2
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 46 deletions.
7 changes: 4 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ travis-ci = { repository = "mdonoughe/sbzdeck" }
[dependencies]
futures = "0.1.25"
indexmap = "1.0"
sbz-switch = "3.0"
sbz-switch = { version = "3.0", git = "https://github.com/mdonoughe/sbz-switch" }
serde = "1.0"
serde_derive = "1.0"
serde_json = "1.0"
Expand Down
85 changes: 49 additions & 36 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ mod types;
use crate::types::*;
use futures::prelude::*;
use futures::sync::mpsc;
use sb::ChangeEvent;
use slog::{crit, debug, error, info, warn, Logger};
use std::collections::BTreeSet;
use std::env;
Expand Down Expand Up @@ -260,47 +261,59 @@ fn main() {
let evt = evt.unwrap();
debug!(logger_events, "saw change: {:?}", evt);
let mut state = state_events.lock().unwrap();
if &evt.feature == "Device Control" && &evt.parameter == "SelectOutput" {
match Output::try_from(&evt.value) {
Some(output) => {
state.output = Some(output);
for context in state.contexts.iter() {
let logger_e = logger_events.clone();
tokio::spawn(
state
.out
.clone()
.send(MessageOut::SetState {
context: context.to_owned(),
payload: StatePayload {
state: output.into(),
},
})
.map_err(move |e| {
error!(logger_e, "failed to queue message: {:?}", e)
})
.map(|_| ()),
match evt {
ChangeEvent::SoundCore(ref evt)
if evt.feature == "Device Control" && evt.parameter == "SelectOutput" =>
{
match Output::try_from(&evt.value) {
Some(output) => {
state.output = Some(output);
for context in state.contexts.iter() {
let logger_e = logger_events.clone();
tokio::spawn(
state
.out
.clone()
.send(MessageOut::SetState {
context: context.to_owned(),
payload: StatePayload {
state: output.into(),
},
})
.map_err(move |e| {
error!(logger_e, "failed to queue message: {:?}", e)
})
.map(|_| ()),
);
}
}
None => {
warn!(
logger_events,
"output device changed to unrecognized value {:?}", evt.value
);
state.output = None;
}
}
None => {
warn!(
logger_events,
"output device changed to unrecognized value {:?}", evt.value
);
state.output = None;
}
ChangeEvent::SoundCore(evt) => {
if let Some(output) = state.output {
// Why update the profile here if we update the profile again right
// before switching? If the user changes a setting and then
// manually switches outputs, we want to capture that setting for
// the next time the user switches back to the original output.
let feature = state.profiles[output]
.parameters
.entry(evt.feature)
.or_default();
feature.insert(evt.parameter, evt.value);
}
}
ChangeEvent::Volume(volume) => {
if let Some(output) = state.output {
state.profiles[output].volume = Some(volume);
}
}
} else if let Some(output) = state.output {
// Why update the profile here if we update the profile again right
// before switching? If the user changes a setting and then
// manually switches outputs, we want to capture that setting for
// the next time the user switches back to the original output.
let feature = state.profiles[output]
.parameters
.entry(evt.feature)
.or_default();
feature.insert(evt.parameter, evt.value);
}
Ok(())
});
Expand Down
25 changes: 19 additions & 6 deletions src/sb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ use crate::types::*;
use futures::prelude::*;
use futures::sync::{mpsc, oneshot};
use indexmap::{IndexMap, IndexSet};
use sbz_switch::media::VolumeNotification;
use sbz_switch::soundcore::{SoundCoreEvent, SoundCoreParamValue};
use sbz_switch::{Configuration, EndpointConfiguration, Win32Error};
use sbz_switch::{Configuration, EndpointConfiguration, SoundCoreOrVolumeEvent, Win32Error};
use slog::error;
use slog::Logger;
use std::{iter, thread};
Expand Down Expand Up @@ -74,7 +75,13 @@ pub fn apply_profile(
}

#[derive(Debug)]
pub struct ChangeEvent {
pub enum ChangeEvent {
SoundCore(SoundCoreChangeEvent),
Volume(f32),
}

#[derive(Debug)]
pub struct SoundCoreChangeEvent {
pub feature: String,
pub parameter: String,
pub value: SoundCoreParamValue,
Expand All @@ -85,24 +92,30 @@ pub fn watch(logger: &Logger) -> Result<mpsc::Receiver<Result<ChangeEvent, Win32
let logger = logger.clone();
thread::Builder::new()
.name("event thread".into())
.spawn(move || match sbz_switch::watch(&logger, None) {
.spawn(move || match sbz_switch::watch_with_volume(&logger, None) {
Ok(iterator) => {
let (event_tx, event_rx) = mpsc::channel(64);
start_tx.send(Ok(event_rx)).unwrap();
let mut event_tx = event_tx.wait();
for event in iterator {
match event {
Ok(SoundCoreEvent::ParamChange { feature, parameter }) => {
Ok(SoundCoreOrVolumeEvent::SoundCore(SoundCoreEvent::ParamChange {
feature,
parameter,
})) => {
let event = match parameter.get() {
Ok(value) => Ok(ChangeEvent {
Ok(value) => Ok(ChangeEvent::SoundCore(SoundCoreChangeEvent {
feature: feature.description.to_owned(),
parameter: parameter.description.to_owned(),
value,
}),
})),
Err(error) => Err(error),
};
event_tx.send(event).unwrap();
}
Ok(SoundCoreOrVolumeEvent::Volume(VolumeNotification {
volume, ..
})) => event_tx.send(Ok(ChangeEvent::Volume(volume))).unwrap(),
Ok(_) => {}
Err(error) => event_tx.send(Err(error)).unwrap(),
}
Expand Down

0 comments on commit 48731d2

Please sign in to comment.