funziona
commit
0012585992
|
|
@ -0,0 +1 @@
|
|||
/target
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
name = "volume"
|
||||
version = "0.1.0"
|
||||
authors = ["Pietro Brenna <pietro.brenna@briq.it>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
actix-web = { version = "3.3.2", default-features = false }
|
||||
ipconfig = "0.2.2"
|
||||
qr2term = "0.2.2"
|
||||
#autopilot = {version = "0.4.0", default-featuers = false }
|
||||
win_key_codes = "0.1.2"
|
||||
winapi = { version = "*", features = ["winuser"] }
|
||||
|
||||
[profile.release]
|
||||
panic = "abort"
|
||||
opt-level = "z"
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>Controlla volume</title>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
|
||||
<style type="text/css">
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-size: 0;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.row1, .row2 {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
height: 50vh;
|
||||
width: 100vw;
|
||||
}
|
||||
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
button {
|
||||
border: none;
|
||||
font-size: calc(min(20vh, 20vw));
|
||||
outline: 0;
|
||||
margin: 0;
|
||||
flex-grow:2;
|
||||
padding: 0;
|
||||
color: #ddd;
|
||||
}
|
||||
|
||||
.down {
|
||||
background: #000;
|
||||
|
||||
}
|
||||
|
||||
.up {
|
||||
background: #444;
|
||||
|
||||
}
|
||||
|
||||
.play_pause {
|
||||
background: #222;
|
||||
|
||||
}
|
||||
.prev {
|
||||
background: #444;
|
||||
}
|
||||
.next {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
button:active {
|
||||
background: #888;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="row1">
|
||||
<button onmousedown="md('down')" onmouseup="mu('down')" class="down">-</button>
|
||||
<button onmousedown="md('up')" onmouseup="mu('up')" class="up">+</button>
|
||||
</div>
|
||||
<div class="row1">
|
||||
<button onmousedown="md('prev')" onmouseup="mu('prev')" class="prev">⏮</button>
|
||||
<button onclick="vol('play_pause')" class="play_pause">⏯</button>
|
||||
<button onmousedown="md('next')" onmouseup="mu('next')" class="next">⏭</button>
|
||||
</div>
|
||||
</body>
|
||||
<script type="text/javascript">
|
||||
var premuto = null;
|
||||
var interval = null;
|
||||
function md(direz) {
|
||||
premuto = direz;
|
||||
vol(premuto);
|
||||
interval = setInterval(function () {
|
||||
vol(premuto);
|
||||
}, 100);
|
||||
}
|
||||
function mu(direz) {
|
||||
clearInterval(interval);
|
||||
}
|
||||
async function vol(direz) {
|
||||
let f = await fetch("/a/" + direz);
|
||||
}
|
||||
</script>
|
||||
|
||||
</html>
|
||||
|
|
@ -0,0 +1,69 @@
|
|||
use actix_web::{web, App, HttpRequest, HttpResponse, HttpServer};
|
||||
use win_key_codes;
|
||||
type WinKeyCode = i32;
|
||||
|
||||
fn win_send_key_event(keycode: WinKeyCode, down: bool, delay_ms: u64) {
|
||||
use winapi::um::winuser::{keybd_event, KEYEVENTF_KEYUP};
|
||||
let flags = if down { 0 } else { KEYEVENTF_KEYUP };
|
||||
unsafe { keybd_event(keycode as u8, 0, flags, 0) };
|
||||
std::thread::sleep(std::time::Duration::from_millis(delay_ms));
|
||||
}
|
||||
|
||||
async fn index(_req: HttpRequest) -> HttpResponse {
|
||||
HttpResponse::Ok()
|
||||
.content_type("text/html")
|
||||
.body(include_str!("index.html"))
|
||||
}
|
||||
async fn action(req: HttpRequest) -> HttpResponse {
|
||||
match req.match_info().get("action") {
|
||||
Some(action) => {
|
||||
let key_code = match action {
|
||||
"up" => win_key_codes::VK_VOLUME_UP,
|
||||
"down" => win_key_codes::VK_VOLUME_DOWN,
|
||||
"play_pause" => win_key_codes::VK_MEDIA_PLAY_PAUSE,
|
||||
"prev" => win_key_codes::VK_LEFT,
|
||||
"next" => win_key_codes::VK_RIGHT,
|
||||
_ => return HttpResponse::BadRequest().body("Bad request"),
|
||||
};
|
||||
win_send_key_event(key_code, true, 10);
|
||||
win_send_key_event(key_code, false, 10);
|
||||
HttpResponse::NoContent().body("")
|
||||
}
|
||||
None => HttpResponse::BadRequest().body("Bad request"),
|
||||
}
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
let port = 8030;
|
||||
println!("Chiudi questa finestra per terminare il programma. Collegati alla porta {} per controllare il volume.", port);
|
||||
let mut candidates = vec![];
|
||||
if let Ok(adapters) = ipconfig::get_adapters() {
|
||||
for adapter in adapters {
|
||||
if adapter.oper_status() == ipconfig::OperStatus::IfOperStatusUp {
|
||||
let desc = adapter.description().to_lowercase().to_string();
|
||||
if !desc.contains("virtual") && !desc.contains("loopback") {
|
||||
for addr in adapter.ip_addresses() {
|
||||
match addr {
|
||||
std::net::IpAddr::V4(v4addr) if v4addr.is_private() => {
|
||||
candidates.push(v4addr.clone());
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if let Some(addr) = candidates.first() {
|
||||
qr2term::print_qr(format!("http://{}:{}/", addr, port)).unwrap();
|
||||
}
|
||||
HttpServer::new(|| {
|
||||
App::new()
|
||||
.route("/", web::get().to(index))
|
||||
.route("/a/{action}", web::get().to(action))
|
||||
})
|
||||
.bind(("0.0.0.0", port))?
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
Loading…
Reference in New Issue