spirc.rs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915
  1. use std;
  2. use std::time::{SystemTime, UNIX_EPOCH};
  3. use futures::{Async, Future, Poll, Sink, Stream};
  4. use futures::future;
  5. use futures::sync::{mpsc, oneshot};
  6. use protobuf::{self, Message};
  7. use rand;
  8. use rand::seq::SliceRandom;
  9. use serde_json;
  10. use context::StationContext;
  11. use core::config::ConnectConfig;
  12. use core::mercury::MercuryError;
  13. use core::session::Session;
  14. use core::spotify_id::SpotifyId;
  15. use core::util::SeqGenerator;
  16. use core::version;
  17. use core::volume::Volume;
  18. use playback::mixer::Mixer;
  19. use playback::player::Player;
  20. use protocol;
  21. use protocol::spirc::{DeviceState, Frame, MessageType, PlayStatus, State};
  22. pub struct SpircTask {
  23. player: Player,
  24. mixer: Box<Mixer>,
  25. linear_volume: bool,
  26. sequence: SeqGenerator<u32>,
  27. ident: String,
  28. device: DeviceState,
  29. state: State,
  30. subscription: Box<Stream<Item = Frame, Error = MercuryError>>,
  31. sender: Box<Sink<SinkItem = Frame, SinkError = MercuryError>>,
  32. commands: mpsc::UnboundedReceiver<SpircCommand>,
  33. end_of_track: Box<Future<Item = (), Error = oneshot::Canceled>>,
  34. shutdown: bool,
  35. session: Session,
  36. context_fut: Box<Future<Item = serde_json::Value, Error = MercuryError>>,
  37. context: Option<StationContext>,
  38. }
  39. pub enum SpircCommand {
  40. Play,
  41. PlayPause,
  42. Pause,
  43. Prev,
  44. Next,
  45. VolumeUp,
  46. VolumeDown,
  47. Shutdown,
  48. }
  49. const CONTEXT_TRACKS_HISTORY: usize = 10;
  50. const CONTEXT_FETCH_THRESHOLD: u32 = 5;
  51. pub struct Spirc {
  52. commands: mpsc::UnboundedSender<SpircCommand>,
  53. }
  54. fn initial_state() -> State {
  55. let mut frame = protocol::spirc::State::new();
  56. frame.set_repeat(false);
  57. frame.set_shuffle(false);
  58. frame.set_status(PlayStatus::kPlayStatusStop);
  59. frame.set_position_ms(0);
  60. frame.set_position_measured_at(0);
  61. frame
  62. }
  63. fn initial_device_state(config: ConnectConfig) -> DeviceState {
  64. {
  65. let mut msg = DeviceState::new();
  66. msg.set_sw_version(version::version_string());
  67. msg.set_is_active(false);
  68. msg.set_can_play(true);
  69. msg.set_volume(0);
  70. msg.set_name(config.name);
  71. {
  72. let repeated = msg.mut_capabilities();
  73. {
  74. let msg = repeated.push_default();
  75. msg.set_typ(protocol::spirc::CapabilityType::kCanBePlayer);
  76. {
  77. let repeated = msg.mut_intValue();
  78. repeated.push(1)
  79. };
  80. msg
  81. };
  82. {
  83. let msg = repeated.push_default();
  84. msg.set_typ(protocol::spirc::CapabilityType::kDeviceType);
  85. {
  86. let repeated = msg.mut_intValue();
  87. repeated.push(config.device_type as i64)
  88. };
  89. msg
  90. };
  91. {
  92. let msg = repeated.push_default();
  93. msg.set_typ(protocol::spirc::CapabilityType::kGaiaEqConnectId);
  94. {
  95. let repeated = msg.mut_intValue();
  96. repeated.push(1)
  97. };
  98. msg
  99. };
  100. {
  101. let msg = repeated.push_default();
  102. msg.set_typ(protocol::spirc::CapabilityType::kSupportsLogout);
  103. {
  104. let repeated = msg.mut_intValue();
  105. repeated.push(0)
  106. };
  107. msg
  108. };
  109. {
  110. let msg = repeated.push_default();
  111. msg.set_typ(protocol::spirc::CapabilityType::kIsObservable);
  112. {
  113. let repeated = msg.mut_intValue();
  114. repeated.push(1)
  115. };
  116. msg
  117. };
  118. {
  119. let msg = repeated.push_default();
  120. msg.set_typ(protocol::spirc::CapabilityType::kVolumeSteps);
  121. {
  122. let repeated = msg.mut_intValue();
  123. repeated.push(64)
  124. };
  125. msg
  126. };
  127. {
  128. let msg = repeated.push_default();
  129. msg.set_typ(protocol::spirc::CapabilityType::kSupportsPlaylistV2);
  130. {
  131. let repeated = msg.mut_intValue();
  132. repeated.push(64)
  133. };
  134. msg
  135. };
  136. {
  137. let msg = repeated.push_default();
  138. msg.set_typ(protocol::spirc::CapabilityType::kSupportedContexts);
  139. {
  140. let repeated = msg.mut_stringValue();
  141. repeated.push(::std::convert::Into::into("album"));
  142. repeated.push(::std::convert::Into::into("playlist"));
  143. repeated.push(::std::convert::Into::into("search"));
  144. repeated.push(::std::convert::Into::into("inbox"));
  145. repeated.push(::std::convert::Into::into("toplist"));
  146. repeated.push(::std::convert::Into::into("starred"));
  147. repeated.push(::std::convert::Into::into("publishedstarred"));
  148. repeated.push(::std::convert::Into::into("track"))
  149. };
  150. msg
  151. };
  152. {
  153. let msg = repeated.push_default();
  154. msg.set_typ(protocol::spirc::CapabilityType::kSupportedTypes);
  155. {
  156. let repeated = msg.mut_stringValue();
  157. repeated.push(::std::convert::Into::into("audio/local"));
  158. repeated.push(::std::convert::Into::into("audio/track"));
  159. repeated.push(::std::convert::Into::into("local"));
  160. repeated.push(::std::convert::Into::into("track"))
  161. };
  162. msg
  163. };
  164. };
  165. msg
  166. }
  167. }
  168. fn calc_logarithmic_volume(volume: u16) -> u16 {
  169. // Volume conversion taken from https://www.dr-lex.be/info-stuff/volumecontrols.html#ideal2
  170. // Convert the given volume [0..0xffff] to a dB gain
  171. // We assume a dB range of 60dB.
  172. // Use the equation: a * exp(b * x)
  173. // in which a = IDEAL_FACTOR, b = 1/1000
  174. const IDEAL_FACTOR: f64 = 6.908;
  175. let normalized_volume = volume as f64 / std::u16::MAX as f64; // To get a value between 0 and 1
  176. let mut val = std::u16::MAX;
  177. // Prevent val > std::u16::MAX due to rounding errors
  178. if normalized_volume < 0.999 {
  179. let new_volume = (normalized_volume * IDEAL_FACTOR).exp() / 1000.0;
  180. val = (new_volume * std::u16::MAX as f64) as u16;
  181. }
  182. debug!("input volume:{} to mixer: {}", volume, val);
  183. // return the scale factor (0..0xffff) (equivalent to a voltage multiplier).
  184. val
  185. }
  186. fn volume_to_mixer(volume: u16, linear_volume: bool) -> u16 {
  187. if linear_volume {
  188. debug!("linear volume: {}", volume);
  189. volume
  190. } else {
  191. calc_logarithmic_volume(volume)
  192. }
  193. }
  194. impl Spirc {
  195. pub fn new(
  196. config: ConnectConfig,
  197. session: Session,
  198. player: Player,
  199. mixer: Box<Mixer>,
  200. ) -> (Spirc, SpircTask) {
  201. debug!("new Spirc[{}]", session.session_id());
  202. let ident = session.device_id().to_owned();
  203. // Uri updated in response to issue #288
  204. let uri = format!("hm://remote/user/{}/", session.username());
  205. let subscription = session.mercury().subscribe(&uri as &str);
  206. let subscription = subscription
  207. .map(|stream| stream.map_err(|_| MercuryError))
  208. .flatten_stream();
  209. let subscription = Box::new(subscription.map(|response| -> Frame {
  210. let data = response.payload.first().unwrap();
  211. protobuf::parse_from_bytes(data).unwrap()
  212. }));
  213. let sender = Box::new(
  214. session
  215. .mercury()
  216. .sender(uri)
  217. .with(|frame: Frame| Ok(frame.write_to_bytes().unwrap())),
  218. );
  219. let (cmd_tx, cmd_rx) = mpsc::unbounded();
  220. let volume = config.volume;
  221. let linear_volume = config.linear_volume;
  222. let device = initial_device_state(config);
  223. let mut task = SpircTask {
  224. player: player,
  225. mixer: mixer,
  226. linear_volume: linear_volume,
  227. sequence: SeqGenerator::new(1),
  228. ident: ident,
  229. device: device,
  230. state: initial_state(),
  231. subscription: subscription,
  232. sender: sender,
  233. commands: cmd_rx,
  234. end_of_track: Box::new(future::empty()),
  235. shutdown: false,
  236. session: session.clone(),
  237. context_fut: Box::new(future::empty()),
  238. context: None,
  239. };
  240. task.set_volume(volume);
  241. let spirc = Spirc { commands: cmd_tx };
  242. task.hello();
  243. (spirc, task)
  244. }
  245. pub fn play(&self) {
  246. let _ = self.commands.unbounded_send(SpircCommand::Play);
  247. }
  248. pub fn play_pause(&self) {
  249. let _ = self.commands.unbounded_send(SpircCommand::PlayPause);
  250. }
  251. pub fn pause(&self) {
  252. let _ = self.commands.unbounded_send(SpircCommand::Pause);
  253. }
  254. pub fn prev(&self) {
  255. let _ = self.commands.unbounded_send(SpircCommand::Prev);
  256. }
  257. pub fn next(&self) {
  258. let _ = self.commands.unbounded_send(SpircCommand::Next);
  259. }
  260. pub fn volume_up(&self) {
  261. let _ = self.commands.unbounded_send(SpircCommand::VolumeUp);
  262. }
  263. pub fn volume_down(&self) {
  264. let _ = self.commands.unbounded_send(SpircCommand::VolumeDown);
  265. }
  266. pub fn shutdown(&self) {
  267. let _ = self.commands.unbounded_send(SpircCommand::Shutdown);
  268. }
  269. }
  270. impl Future for SpircTask {
  271. type Item = ();
  272. type Error = ();
  273. fn poll(&mut self) -> Poll<(), ()> {
  274. loop {
  275. let mut progress = false;
  276. if self.session.is_invalid() {
  277. return Ok(Async::Ready(()));
  278. }
  279. if !self.shutdown {
  280. match self.subscription.poll().unwrap() {
  281. Async::Ready(Some(frame)) => {
  282. progress = true;
  283. self.handle_frame(frame);
  284. }
  285. Async::Ready(None) => panic!("subscription terminated"),
  286. Async::NotReady => (),
  287. }
  288. match self.commands.poll().unwrap() {
  289. Async::Ready(Some(command)) => {
  290. progress = true;
  291. self.handle_command(command);
  292. }
  293. Async::Ready(None) => (),
  294. Async::NotReady => (),
  295. }
  296. match self.end_of_track.poll() {
  297. Ok(Async::Ready(())) => {
  298. progress = true;
  299. self.handle_end_of_track();
  300. }
  301. Ok(Async::NotReady) => (),
  302. Err(oneshot::Canceled) => self.end_of_track = Box::new(future::empty()),
  303. }
  304. match self.context_fut.poll() {
  305. Ok(Async::Ready(value)) => {
  306. let r_context = serde_json::from_value::<StationContext>(value.clone());
  307. self.context = match r_context {
  308. Ok(context) => {
  309. info!(
  310. "Resolved {:?} tracks from <{:?}>",
  311. context.tracks.len(),
  312. self.state.get_context_uri(),
  313. );
  314. Some(context)
  315. }
  316. Err(e) => {
  317. error!("Unable to parse JSONContext {:?}\n{:?}", e, value);
  318. None
  319. }
  320. };
  321. // It needn't be so verbose - can be as simple as
  322. // if let Some(ref context) = r_context {
  323. // info!("Got {:?} tracks from <{}>", context.tracks.len(), context.uri);
  324. // }
  325. // self.context = r_context;
  326. progress = true;
  327. self.context_fut = Box::new(future::empty());
  328. }
  329. Ok(Async::NotReady) => (),
  330. Err(err) => {
  331. self.context_fut = Box::new(future::empty());
  332. error!("ContextError: {:?}", err)
  333. }
  334. }
  335. }
  336. let poll_sender = self.sender.poll_complete().unwrap();
  337. // Only shutdown once we've flushed out all our messages
  338. if self.shutdown && poll_sender.is_ready() {
  339. return Ok(Async::Ready(()));
  340. }
  341. if !progress {
  342. return Ok(Async::NotReady);
  343. }
  344. }
  345. }
  346. }
  347. impl SpircTask {
  348. fn now_ms(&mut self) -> i64 {
  349. let dur = match SystemTime::now().duration_since(UNIX_EPOCH) {
  350. Ok(dur) => dur,
  351. Err(err) => err.duration(),
  352. };
  353. ((dur.as_secs() + self.session.time_delta()) * 1000 + (dur.subsec_nanos() / 1000_000) as u64) as i64
  354. }
  355. fn handle_command(&mut self, cmd: SpircCommand) {
  356. let active = self.device.get_is_active();
  357. match cmd {
  358. SpircCommand::Play => {
  359. if active {
  360. self.handle_play();
  361. self.notify(None);
  362. } else {
  363. CommandSender::new(self, MessageType::kMessageTypePlay).send();
  364. }
  365. }
  366. SpircCommand::PlayPause => {
  367. if active {
  368. self.handle_play_pause();
  369. self.notify(None);
  370. } else {
  371. CommandSender::new(self, MessageType::kMessageTypePlayPause).send();
  372. }
  373. }
  374. SpircCommand::Pause => {
  375. if active {
  376. self.handle_pause();
  377. self.notify(None);
  378. } else {
  379. CommandSender::new(self, MessageType::kMessageTypePause).send();
  380. }
  381. }
  382. SpircCommand::Prev => {
  383. if active {
  384. self.handle_prev();
  385. self.notify(None);
  386. } else {
  387. CommandSender::new(self, MessageType::kMessageTypePrev).send();
  388. }
  389. }
  390. SpircCommand::Next => {
  391. if active {
  392. self.handle_next();
  393. self.notify(None);
  394. } else {
  395. CommandSender::new(self, MessageType::kMessageTypeNext).send();
  396. }
  397. }
  398. SpircCommand::VolumeUp => {
  399. if active {
  400. self.handle_volume_up();
  401. self.notify(None);
  402. } else {
  403. CommandSender::new(self, MessageType::kMessageTypeVolumeUp).send();
  404. }
  405. }
  406. SpircCommand::VolumeDown => {
  407. if active {
  408. self.handle_volume_down();
  409. self.notify(None);
  410. } else {
  411. CommandSender::new(self, MessageType::kMessageTypeVolumeDown).send();
  412. }
  413. }
  414. SpircCommand::Shutdown => {
  415. CommandSender::new(self, MessageType::kMessageTypeGoodbye).send();
  416. self.shutdown = true;
  417. self.commands.close();
  418. }
  419. }
  420. }
  421. fn handle_frame(&mut self, frame: Frame) {
  422. debug!(
  423. "{:?} {:?} {} {} {}",
  424. frame.get_typ(),
  425. frame.get_device_state().get_name(),
  426. frame.get_ident(),
  427. frame.get_seq_nr(),
  428. frame.get_state_update_id()
  429. );
  430. if frame.get_ident() == self.ident
  431. || (frame.get_recipient().len() > 0 && !frame.get_recipient().contains(&self.ident))
  432. {
  433. return;
  434. }
  435. match frame.get_typ() {
  436. MessageType::kMessageTypeHello => {
  437. self.notify(Some(frame.get_ident()));
  438. }
  439. MessageType::kMessageTypeLoad => {
  440. if !self.device.get_is_active() {
  441. let now = self.now_ms();
  442. self.device.set_is_active(true);
  443. self.device.set_became_active_at(now);
  444. }
  445. self.update_tracks(&frame);
  446. if self.state.get_track().len() > 0 {
  447. let now = self.now_ms();
  448. self.state.set_position_ms(frame.get_state().get_position_ms());
  449. self.state.set_position_measured_at(now as u64);
  450. let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay;
  451. self.load_track(play);
  452. } else {
  453. info!("No more tracks left in queue");
  454. self.state.set_status(PlayStatus::kPlayStatusStop);
  455. }
  456. self.notify(None);
  457. }
  458. MessageType::kMessageTypePlay => {
  459. self.handle_play();
  460. self.notify(None);
  461. }
  462. MessageType::kMessageTypePlayPause => {
  463. self.handle_play_pause();
  464. self.notify(None);
  465. }
  466. MessageType::kMessageTypePause => {
  467. self.handle_pause();
  468. self.notify(None);
  469. }
  470. MessageType::kMessageTypeNext => {
  471. self.handle_next();
  472. self.notify(None);
  473. }
  474. MessageType::kMessageTypePrev => {
  475. self.handle_prev();
  476. self.notify(None);
  477. }
  478. MessageType::kMessageTypeVolumeUp => {
  479. self.handle_volume_up();
  480. self.notify(None);
  481. }
  482. MessageType::kMessageTypeVolumeDown => {
  483. self.handle_volume_down();
  484. self.notify(None);
  485. }
  486. MessageType::kMessageTypeRepeat => {
  487. self.state.set_repeat(frame.get_state().get_repeat());
  488. self.notify(None);
  489. }
  490. MessageType::kMessageTypeShuffle => {
  491. self.state.set_shuffle(frame.get_state().get_shuffle());
  492. if self.state.get_shuffle() {
  493. let current_index = self.state.get_playing_track_index();
  494. {
  495. let tracks = self.state.mut_track();
  496. tracks.swap(0, current_index as usize);
  497. if let Some((_, rest)) = tracks.split_first_mut() {
  498. let mut rng = rand::thread_rng();
  499. rest.shuffle(&mut rng);
  500. }
  501. }
  502. self.state.set_playing_track_index(0);
  503. } else {
  504. let context = self.state.get_context_uri();
  505. debug!("{:?}", context);
  506. }
  507. self.notify(None);
  508. }
  509. MessageType::kMessageTypeSeek => {
  510. let position = frame.get_position();
  511. let now = self.now_ms();
  512. self.state.set_position_ms(position);
  513. self.state.set_position_measured_at(now as u64);
  514. self.player.seek(position);
  515. self.notify(None);
  516. }
  517. MessageType::kMessageTypeReplace => {
  518. self.update_tracks(&frame);
  519. self.notify(None);
  520. }
  521. MessageType::kMessageTypeVolume => {
  522. self.set_volume(frame.get_volume() as u16);
  523. self.notify(None);
  524. }
  525. MessageType::kMessageTypeNotify => {
  526. if self.device.get_is_active() && frame.get_device_state().get_is_active() {
  527. self.device.set_is_active(false);
  528. self.state.set_status(PlayStatus::kPlayStatusStop);
  529. self.player.stop();
  530. self.mixer.stop();
  531. }
  532. }
  533. _ => (),
  534. }
  535. }
  536. fn handle_play(&mut self) {
  537. if self.state.get_status() == PlayStatus::kPlayStatusPause {
  538. self.mixer.start();
  539. self.player.play();
  540. self.state.set_status(PlayStatus::kPlayStatusPlay);
  541. let now = self.now_ms();
  542. self.state.set_position_measured_at(now as u64);
  543. }
  544. }
  545. fn handle_play_pause(&mut self) {
  546. match self.state.get_status() {
  547. PlayStatus::kPlayStatusPlay => self.handle_pause(),
  548. PlayStatus::kPlayStatusPause => self.handle_play(),
  549. _ => (),
  550. }
  551. }
  552. fn handle_pause(&mut self) {
  553. if self.state.get_status() == PlayStatus::kPlayStatusPlay {
  554. self.player.pause();
  555. self.mixer.stop();
  556. self.state.set_status(PlayStatus::kPlayStatusPause);
  557. let now = self.now_ms() as u64;
  558. let position = self.state.get_position_ms();
  559. let diff = now - self.state.get_position_measured_at();
  560. self.state.set_position_ms(position + diff as u32);
  561. self.state.set_position_measured_at(now);
  562. }
  563. }
  564. fn consume_queued_track(&mut self) -> usize {
  565. // Removes current track if it is queued
  566. // Returns the index of the next track
  567. let current_index = self.state.get_playing_track_index() as usize;
  568. if self.state.get_track()[current_index].get_queued() {
  569. self.state.mut_track().remove(current_index);
  570. return current_index;
  571. }
  572. current_index + 1
  573. }
  574. fn handle_next(&mut self) {
  575. let mut new_index = self.consume_queued_track() as u32;
  576. let mut continue_playing = true;
  577. debug!(
  578. "At track {:?} of {:?} <{:?}> update [{}]",
  579. new_index,
  580. self.state.get_track().len(),
  581. self.state.get_context_uri(),
  582. self.state.get_track().len() as u32 - new_index < CONTEXT_FETCH_THRESHOLD
  583. );
  584. let context_uri = self.state.get_context_uri().to_owned();
  585. if (context_uri.starts_with("spotify:station:") || context_uri.starts_with("spotify:dailymix:"))
  586. && ((self.state.get_track().len() as u32) - new_index) < CONTEXT_FETCH_THRESHOLD
  587. {
  588. self.context_fut = self.resolve_station(&context_uri);
  589. self.update_tracks_from_context();
  590. }
  591. if new_index >= self.state.get_track().len() as u32 {
  592. new_index = 0; // Loop around back to start
  593. continue_playing = self.state.get_repeat();
  594. }
  595. self.state.set_playing_track_index(new_index);
  596. self.state.set_position_ms(0);
  597. let now = self.now_ms();
  598. self.state.set_position_measured_at(now as u64);
  599. self.load_track(continue_playing);
  600. }
  601. fn handle_prev(&mut self) {
  602. // Previous behaves differently based on the position
  603. // Under 3s it goes to the previous song (starts playing)
  604. // Over 3s it seeks to zero (retains previous play status)
  605. if self.position() < 3000 {
  606. // Queued tracks always follow the currently playing track.
  607. // They should not be considered when calculating the previous
  608. // track so extract them beforehand and reinsert them after it.
  609. let mut queue_tracks = Vec::new();
  610. {
  611. let queue_index = self.consume_queued_track();
  612. let tracks = self.state.mut_track();
  613. while queue_index < tracks.len() && tracks[queue_index].get_queued() {
  614. queue_tracks.push(tracks.remove(queue_index));
  615. }
  616. }
  617. let current_index = self.state.get_playing_track_index();
  618. let new_index = if current_index > 0 {
  619. current_index - 1
  620. } else if self.state.get_repeat() {
  621. self.state.get_track().len() as u32 - 1
  622. } else {
  623. 0
  624. };
  625. // Reinsert queued tracks after the new playing track.
  626. let mut pos = (new_index + 1) as usize;
  627. for track in queue_tracks.into_iter() {
  628. self.state.mut_track().insert(pos, track);
  629. pos += 1;
  630. }
  631. let now = self.now_ms();
  632. self.state.set_playing_track_index(new_index);
  633. self.state.set_position_ms(0);
  634. self.state.set_position_measured_at(now as u64);
  635. self.load_track(true);
  636. } else {
  637. let now = self.now_ms();
  638. self.state.set_position_ms(0);
  639. self.state.set_position_measured_at(now as u64);
  640. self.player.seek(0);
  641. }
  642. }
  643. fn handle_volume_up(&mut self) {
  644. let mut volume: u32 = self.device.get_volume() as u32 + 4096;
  645. if volume > 0xFFFF {
  646. volume = 0xFFFF;
  647. }
  648. self.set_volume(volume as u16);
  649. }
  650. fn handle_volume_down(&mut self) {
  651. let mut volume: i32 = self.device.get_volume() as i32 - 4096;
  652. if volume < 0 {
  653. volume = 0;
  654. }
  655. self.set_volume(volume as u16);
  656. }
  657. fn handle_end_of_track(&mut self) {
  658. self.handle_next();
  659. self.notify(None);
  660. }
  661. fn position(&mut self) -> u32 {
  662. let diff = self.now_ms() as u64 - self.state.get_position_measured_at();
  663. self.state.get_position_ms() + diff as u32
  664. }
  665. fn resolve_station(&self, uri: &str) -> Box<Future<Item = serde_json::Value, Error = MercuryError>> {
  666. let radio_uri = format!("hm://radio-apollo/v3/stations/{}", uri);
  667. self.resolve_uri(&radio_uri)
  668. }
  669. fn resolve_uri(&self, uri: &str) -> Box<Future<Item = serde_json::Value, Error = MercuryError>> {
  670. let request = self.session.mercury().get(uri);
  671. Box::new(request.and_then(move |response| {
  672. let data = response.payload.first().expect("Empty payload on context uri");
  673. let response: serde_json::Value = serde_json::from_slice(&data).unwrap();
  674. Ok(response)
  675. }))
  676. }
  677. fn update_tracks_from_context(&mut self) {
  678. if let Some(ref context) = self.context {
  679. self.context_fut = self.resolve_uri(&context.next_page_url);
  680. let new_tracks = &context.tracks;
  681. debug!("Adding {:?} tracks from context to playlist", new_tracks.len());
  682. let current_index = self.state.get_playing_track_index();
  683. let mut new_index = 0;
  684. {
  685. let mut tracks = self.state.mut_track();
  686. // Does this need to be optimised - we don't need to actually traverse the len of tracks
  687. let tracks_len = tracks.len();
  688. if tracks_len > CONTEXT_TRACKS_HISTORY {
  689. tracks.rotate_right(tracks_len - CONTEXT_TRACKS_HISTORY);
  690. tracks.truncate(CONTEXT_TRACKS_HISTORY);
  691. }
  692. // tracks.extend_from_slice(&mut new_tracks); // method doesn't exist for protobuf::RepeatedField
  693. for t in new_tracks {
  694. tracks.push(t.to_owned());
  695. }
  696. if current_index > CONTEXT_TRACKS_HISTORY as u32 {
  697. new_index = current_index - CONTEXT_TRACKS_HISTORY as u32;
  698. }
  699. }
  700. self.state.set_playing_track_index(new_index);
  701. }
  702. }
  703. fn update_tracks(&mut self, frame: &protocol::spirc::Frame) {
  704. let index = frame.get_state().get_playing_track_index();
  705. let context_uri = frame.get_state().get_context_uri().to_owned();
  706. let tracks = frame.get_state().get_track();
  707. debug!("Frame has {:?} tracks", tracks.len());
  708. if context_uri.starts_with("spotify:station:") || context_uri.starts_with("spotify:dailymix:") {
  709. self.context_fut = self.resolve_station(&context_uri);
  710. }
  711. self.state.set_playing_track_index(index);
  712. self.state.set_track(tracks.into_iter().cloned().collect());
  713. self.state.set_context_uri(context_uri);
  714. self.state.set_repeat(frame.get_state().get_repeat());
  715. self.state.set_shuffle(frame.get_state().get_shuffle());
  716. }
  717. fn load_track(&mut self, play: bool) {
  718. let track = {
  719. let mut index = self.state.get_playing_track_index();
  720. // Check for malformed gid
  721. let tracks_len = self.state.get_track().len() as u32;
  722. let mut track_ref = &self.state.get_track()[index as usize];
  723. while track_ref.get_gid().len() != 16 {
  724. warn!(
  725. "Skipping track {:?} at position [{}] of {}",
  726. track_ref.get_uri(),
  727. index,
  728. tracks_len
  729. );
  730. index = if index + 1 < tracks_len { index + 1 } else { 0 };
  731. track_ref = &self.state.get_track()[index as usize];
  732. }
  733. SpotifyId::from_raw(track_ref.get_gid()).unwrap()
  734. };
  735. let position = self.state.get_position_ms();
  736. let end_of_track = self.player.load(track, play, position);
  737. if play {
  738. self.state.set_status(PlayStatus::kPlayStatusPlay);
  739. } else {
  740. self.state.set_status(PlayStatus::kPlayStatusPause);
  741. }
  742. self.end_of_track = Box::new(end_of_track);
  743. }
  744. fn hello(&mut self) {
  745. CommandSender::new(self, MessageType::kMessageTypeHello).send();
  746. }
  747. fn notify(&mut self, recipient: Option<&str>) {
  748. let mut cs = CommandSender::new(self, MessageType::kMessageTypeNotify);
  749. if let Some(s) = recipient {
  750. cs = cs.recipient(&s);
  751. }
  752. cs.send();
  753. }
  754. fn set_volume(&mut self, volume: u16) {
  755. self.device.set_volume(volume as u32);
  756. self.mixer.set_volume(volume_to_mixer(volume, self.linear_volume));
  757. if let Some(cache) = self.session.cache() {
  758. cache.save_volume(Volume { volume })
  759. }
  760. }
  761. }
  762. impl Drop for SpircTask {
  763. fn drop(&mut self) {
  764. debug!("drop Spirc[{}]", self.session.session_id());
  765. }
  766. }
  767. struct CommandSender<'a> {
  768. spirc: &'a mut SpircTask,
  769. frame: protocol::spirc::Frame,
  770. }
  771. impl<'a> CommandSender<'a> {
  772. fn new(spirc: &'a mut SpircTask, cmd: MessageType) -> CommandSender {
  773. let mut frame = protocol::spirc::Frame::new();
  774. frame.set_version(1);
  775. frame.set_protocol_version(::std::convert::Into::into("2.0.0"));
  776. frame.set_ident(spirc.ident.clone());
  777. frame.set_seq_nr(spirc.sequence.get());
  778. frame.set_typ(cmd);
  779. frame.set_device_state(spirc.device.clone());
  780. frame.set_state_update_id(spirc.now_ms());
  781. CommandSender {
  782. spirc: spirc,
  783. frame: frame,
  784. }
  785. }
  786. fn recipient(mut self, recipient: &'a str) -> CommandSender {
  787. self.frame.mut_recipient().push(recipient.to_owned());
  788. self
  789. }
  790. #[allow(dead_code)]
  791. fn state(mut self, state: protocol::spirc::State) -> CommandSender<'a> {
  792. self.frame.set_state(state);
  793. self
  794. }
  795. fn send(mut self) {
  796. if !self.frame.has_state() && self.spirc.device.get_is_active() {
  797. self.frame.set_state(self.spirc.state.clone());
  798. }
  799. let send = self.spirc.sender.start_send(self.frame).unwrap();
  800. assert!(send.is_ready());
  801. }
  802. }