|
@@ -8,6 +8,7 @@ use std::mem;
|
|
|
use std::path::PathBuf;
|
|
|
use std::process::exit;
|
|
|
use std::str::FromStr;
|
|
|
+use std::time::Instant;
|
|
|
use tokio_core::reactor::{Core, Handle};
|
|
|
use tokio_io::IoStream;
|
|
|
use url::Url;
|
|
@@ -375,6 +376,8 @@ struct Main {
|
|
|
connect: Box<dyn Future<Item = Session, Error = io::Error>>,
|
|
|
|
|
|
shutdown: bool,
|
|
|
+ last_credentials: Option<Credentials>,
|
|
|
+ auto_connect_times: Vec<Instant>,
|
|
|
|
|
|
player_event_channel: Option<UnboundedReceiver<PlayerEvent>>,
|
|
|
player_event_program: Option<String>,
|
|
@@ -398,6 +401,8 @@ impl Main {
|
|
|
spirc: None,
|
|
|
spirc_task: None,
|
|
|
shutdown: false,
|
|
|
+ last_credentials: None,
|
|
|
+ auto_connect_times: Vec::new(),
|
|
|
signal: Box::new(tokio_signal::ctrl_c().flatten_stream()),
|
|
|
|
|
|
player_event_channel: None,
|
|
@@ -420,6 +425,7 @@ impl Main {
|
|
|
}
|
|
|
|
|
|
fn credentials(&mut self, credentials: Credentials) {
|
|
|
+ self.last_credentials = Some(credentials.clone());
|
|
|
let config = self.session_config.clone();
|
|
|
let handle = self.handle.clone();
|
|
|
|
|
@@ -448,32 +454,40 @@ impl Future for Main {
|
|
|
if let Some(ref spirc) = self.spirc {
|
|
|
spirc.shutdown();
|
|
|
}
|
|
|
+ self.auto_connect_times.clear();
|
|
|
self.credentials(creds);
|
|
|
|
|
|
progress = true;
|
|
|
}
|
|
|
|
|
|
- if let Async::Ready(session) = self.connect.poll().unwrap() {
|
|
|
- self.connect = Box::new(futures::future::empty());
|
|
|
- let mixer_config = self.mixer_config.clone();
|
|
|
- let mixer = (self.mixer)(Some(mixer_config));
|
|
|
- let player_config = self.player_config.clone();
|
|
|
- let connect_config = self.connect_config.clone();
|
|
|
-
|
|
|
- let audio_filter = mixer.get_audio_filter();
|
|
|
- let backend = self.backend;
|
|
|
- let device = self.device.clone();
|
|
|
- let (player, event_channel) =
|
|
|
- Player::new(player_config, session.clone(), audio_filter, move || {
|
|
|
- (backend)(device)
|
|
|
- });
|
|
|
-
|
|
|
- let (spirc, spirc_task) = Spirc::new(connect_config, session, player, mixer);
|
|
|
- self.spirc = Some(spirc);
|
|
|
- self.spirc_task = Some(spirc_task);
|
|
|
- self.player_event_channel = Some(event_channel);
|
|
|
-
|
|
|
- progress = true;
|
|
|
+ match self.connect.poll() {
|
|
|
+ Ok(Async::Ready(session)) => {
|
|
|
+ self.connect = Box::new(futures::future::empty());
|
|
|
+ let mixer_config = self.mixer_config.clone();
|
|
|
+ let mixer = (self.mixer)(Some(mixer_config));
|
|
|
+ let player_config = self.player_config.clone();
|
|
|
+ let connect_config = self.connect_config.clone();
|
|
|
+
|
|
|
+ let audio_filter = mixer.get_audio_filter();
|
|
|
+ let backend = self.backend;
|
|
|
+ let device = self.device.clone();
|
|
|
+ let (player, event_channel) =
|
|
|
+ Player::new(player_config, session.clone(), audio_filter, move || {
|
|
|
+ (backend)(device)
|
|
|
+ });
|
|
|
+
|
|
|
+ let (spirc, spirc_task) = Spirc::new(connect_config, session, player, mixer);
|
|
|
+ self.spirc = Some(spirc);
|
|
|
+ self.spirc_task = Some(spirc_task);
|
|
|
+ self.player_event_channel = Some(event_channel);
|
|
|
+
|
|
|
+ progress = true;
|
|
|
+ }
|
|
|
+ Ok(Async::NotReady) => (),
|
|
|
+ Err(error) => {
|
|
|
+ error!("Could not connect to server: {}", error);
|
|
|
+ self.connect = Box::new(futures::future::empty());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
if let Async::Ready(Some(())) = self.signal.poll().unwrap() {
|
|
@@ -492,12 +506,32 @@ impl Future for Main {
|
|
|
progress = true;
|
|
|
}
|
|
|
|
|
|
+ let mut drop_spirc_and_try_to_reconnect = false;
|
|
|
if let Some(ref mut spirc_task) = self.spirc_task {
|
|
|
if let Async::Ready(()) = spirc_task.poll().unwrap() {
|
|
|
if self.shutdown {
|
|
|
return Ok(Async::Ready(()));
|
|
|
} else {
|
|
|
- panic!("Spirc shut down unexpectedly");
|
|
|
+ warn!("Spirc shut down unexpectedly");
|
|
|
+ drop_spirc_and_try_to_reconnect = true;
|
|
|
+ }
|
|
|
+ progress = true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if drop_spirc_and_try_to_reconnect {
|
|
|
+ self.spirc_task = None;
|
|
|
+ while (!self.auto_connect_times.is_empty())
|
|
|
+ && ((Instant::now() - self.auto_connect_times[0]).as_secs() > 600)
|
|
|
+ {
|
|
|
+ let _ = self.auto_connect_times.remove(0);
|
|
|
+ }
|
|
|
+
|
|
|
+ if let Some(credentials) = self.last_credentials.clone() {
|
|
|
+ if self.auto_connect_times.len() >= 5 {
|
|
|
+ warn!("Spirc shut down too often. Not reconnecting automatically.");
|
|
|
+ } else {
|
|
|
+ self.auto_connect_times.push(Instant::now());
|
|
|
+ self.credentials(credentials);
|
|
|
}
|
|
|
}
|
|
|
}
|