initial commit
This commit is contained in:
commit
f1ca8d6431
|
@ -0,0 +1,3 @@
|
||||||
|
/target
|
||||||
|
Cargo.lock
|
||||||
|
.vscode/
|
|
@ -0,0 +1,12 @@
|
||||||
|
[package]
|
||||||
|
name = "synth-notifications"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Agatha Rose <agatharose@wantscuddl.es>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
dbus = "0.9.3"
|
||||||
|
midi-control = "0.2.0"
|
||||||
|
midir = "0.7.0"
|
|
@ -0,0 +1,104 @@
|
||||||
|
use std::{
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
|
|
||||||
|
use dbus::blocking::Connection;
|
||||||
|
use dbus::message::MatchRule;
|
||||||
|
use dbus::Message;
|
||||||
|
use dbus::{arg::messageitem::MessageItem, channel::MatchingReceiver};
|
||||||
|
use midi_control::*;
|
||||||
|
use midir::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let midi_device = MidiOutput::new("synth output meow").expect("could not find device");
|
||||||
|
let ports = midi_device.ports();
|
||||||
|
// assumes that the device is connected on port 1
|
||||||
|
// TODO: add port selection
|
||||||
|
let midi_out = midi_device
|
||||||
|
.connect(&ports[1], "meow port")
|
||||||
|
.expect("oh dear");
|
||||||
|
let midi_out = Arc::new(Mutex::new(midi_out));
|
||||||
|
|
||||||
|
// monitor dbus notifications
|
||||||
|
let conn = Connection::new_session().unwrap();
|
||||||
|
let mut rule = MatchRule::new();
|
||||||
|
|
||||||
|
let proxy = conn.with_proxy(
|
||||||
|
"org.freedesktop.DBus",
|
||||||
|
"/org/freedesktop/DBus",
|
||||||
|
Duration::from_millis(5000),
|
||||||
|
);
|
||||||
|
let result: Result<(), dbus::Error> = proxy.method_call(
|
||||||
|
"org.freedesktop.Notifications",
|
||||||
|
"BecomeMonitor",
|
||||||
|
(vec![rule.match_str()], 0u32),
|
||||||
|
);
|
||||||
|
|
||||||
|
if result.is_ok() {
|
||||||
|
// Start matching using new scheme
|
||||||
|
conn.start_receive(
|
||||||
|
rule,
|
||||||
|
Box::new(move |msg, _| {
|
||||||
|
midi_hook(midi_out.clone(), &msg);
|
||||||
|
true
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Start matching using old scheme
|
||||||
|
rule.eavesdrop = true;
|
||||||
|
conn.add_match(rule, move |_: (), _, msg| {
|
||||||
|
midi_hook(midi_out.clone(), &msg);
|
||||||
|
true
|
||||||
|
})
|
||||||
|
.expect("add_match failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
loop {
|
||||||
|
conn.process(Duration::from_millis(1000)).unwrap();
|
||||||
|
}
|
||||||
|
// TODO: use the ctrlc crate to handle the midi connection closing
|
||||||
|
}
|
||||||
|
|
||||||
|
fn midi_hook(midi_out: Arc<Mutex<MidiOutputConnection>>, msg: &Message) {
|
||||||
|
let args = msg.get_items();
|
||||||
|
|
||||||
|
// do nothing if args are empty
|
||||||
|
if args.is_empty() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only apply to firefox notifications
|
||||||
|
// TODO: make browser name configurable
|
||||||
|
if args[0] == "Nightly".into() {
|
||||||
|
// get the dict of values inside the message's args
|
||||||
|
let dict_values = match &args[6] {
|
||||||
|
MessageItem::Dict(v) => v.clone().into_vec(),
|
||||||
|
_ => Vec::new(),
|
||||||
|
};
|
||||||
|
|
||||||
|
{
|
||||||
|
// if the key equals "sender-pid", the message is a duplicate of the last one
|
||||||
|
let (v, _) = &dict_values[&dict_values.len() - 1];
|
||||||
|
if v == &"sender-pid".into() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Got a notification from {:?}!", args[0]);
|
||||||
|
|
||||||
|
// TODO: make note pitch and duration configurable
|
||||||
|
let play_note = midi_control::note_on(Channel::Ch1, 40, 127);
|
||||||
|
let stop_note = midi_control::note_off(Channel::Ch1, 40, 127);
|
||||||
|
|
||||||
|
let mut midi_out = midi_out.lock().expect("couldn't acquire midi connection");
|
||||||
|
|
||||||
|
midi_out
|
||||||
|
.send_message(play_note)
|
||||||
|
.expect("could not play note");
|
||||||
|
std::thread::sleep(Duration::from_millis(2000));
|
||||||
|
midi_out
|
||||||
|
.send_message(stop_note)
|
||||||
|
.expect("could not stop play note");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue