1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
#[cfg(test)]
#[macro_use]
extern crate indoc;
extern crate clap;
extern crate colored;
extern crate tokio;
extern crate hyper;
extern crate futures;
use colored::*;
use clap::{Arg, App};
use std::path::Path;
use std::process;
use std::thread;
use std::sync::mpsc;
use hyper::{Client, Server, Request};
use hyper::body::Body;
use hyper::service::service_fn;
use tokio::runtime::Runtime;
use futures::Future;
mod cli;
mod upnp;
mod serve;
mod notify;
fn main() {
let app = App::new(env!("CARGO_PKG_NAME"))
.version(env!("CARGO_PKG_VERSION"))
.author("Yuval Adam")
.about(env!("CARGO_PKG_DESCRIPTION"))
.arg(Arg::with_name("device")
.short("d")
.long("device")
.value_name("DEVICE")
.help("Target specific device address"))
.arg(Arg::with_name("subtitles")
.short("s")
.long("subtitles")
.value_name("SUBTITLES")
.help("Subtitles file to use with the video"))
.arg(Arg::with_name("FILE")
.value_name("FILE")
.help("Media file to stream")
.index(1)
.required(true));
let matches = app.get_matches();
let infile = matches.value_of("FILE").unwrap();
if Path::new(infile).exists() {
println!("\n{} {}\n", "Using input file:".green(), infile.green());
}
else {
println!("\n{} {}\n", "Input file does not exist:".red(), infile.red());
process::exit(1);
}
let addr = "0.0.0.0:51497".parse().unwrap();
let server = Server::bind(&addr)
.serve(|| service_fn(serve::response_examples))
.map_err(|e| eprintln!("server error: {}", e));
println!("Listening on http://{}", addr);
let mut rt = Runtime::new().unwrap();
rt.spawn(server);
let client = Client::new();
let req1 = Request::builder()
.method("POST")
.uri("http://10.5.1.201:38400/serviceControl/AVTransport")
.header("Content-Type", "text/xml")
.header("SOAPACTION", notify::A_SET)
.body(Body::from(notify::BODY_SET_URI))
.unwrap();
// let req2 = Request::builder()
// .method("POST")
// .uri("http://10.5.1.201:38400/serviceControl/AVTransport")
// .header("Content-Type", "text/xml")
// .header("SOAPACTION", notify::A_STOP)
// .body(Body::from(notify::BODY_STOP))
// .unwrap();
let f = client
.request(req1)
.map(|res| {
println!("OK")
})
.map_err(|err| {
println!("Something bad happened");
});
// .and_then(move |_| {
// client.request(req2).map(|res| {
// println!("OK");
// }).map_err(|err| {
// println!("Something bad2");
// })
// });
rt.spawn(f);
// let _udp = thread::spawn(move || {
// upnp::discover();
// });
let (tx, rx) = mpsc::channel();
let child = thread::spawn(move || {
let mut controller = cli::Controller::init();
loop {
let c = controller.read();
tx.send(c).unwrap();
if c == 113 {
break;
}
if c == 32 {
let req2 = Request::builder()
.method("POST")
.uri("http://10.5.1.201:38400/serviceControl/AVTransport")
.header("Content-Type", "text/xml")
.header("SOAPACTION", notify::A_PLAY)
.body(Body::from(notify::BODY_PLAY))
.unwrap();
let f = client.request(req2).map(|res| {
println!("OK");
}).map_err(|err| {
println!("Err");
});
rt.spawn(f);
}
}
controller.destroy();
});
for received in rx {
println!("Got char: {}", received);
}
println!("Waiting for all thread");
let _res = child.join();
println!("Done!");
}
|