spirc.rs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912
  1. use std;
  2. use std::time::{SystemTime, UNIX_EPOCH};
  3. use futures::future;
  4. use futures::sync::{mpsc, oneshot};
  5. use futures::{Async, Future, Poll, Sink, Stream};
  6. use protobuf::{self, Message};
  7. use rand;
  8. use rand::seq::SliceRandom;
  9. use serde_json;
  10. use context::StationContext;
  11. use librespot_core::config::ConnectConfig;
  12. use librespot_core::mercury::MercuryError;
  13. use librespot_core::session::Session;
  14. use librespot_core::spotify_id::SpotifyId;
  15. use librespot_core::util::SeqGenerator;
  16. use librespot_core::version;
  17. use librespot_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() as i64 + self.session.time_delta()) * 1000
  354. + (dur.subsec_nanos() / 1000_000) as i64)
  355. }
  356. fn handle_command(&mut self, cmd: SpircCommand) {
  357. let active = self.device.get_is_active();
  358. match cmd {
  359. SpircCommand::Play => {
  360. if active {
  361. self.handle_play();
  362. self.notify(None);
  363. } else {
  364. CommandSender::new(self, MessageType::kMessageTypePlay).send();
  365. }
  366. }
  367. SpircCommand::PlayPause => {
  368. if active {
  369. self.handle_play_pause();
  370. self.notify(None);
  371. } else {
  372. CommandSender::new(self, MessageType::kMessageTypePlayPause).send();
  373. }
  374. }
  375. SpircCommand::Pause => {
  376. if active {
  377. self.handle_pause();
  378. self.notify(None);
  379. } else {
  380. CommandSender::new(self, MessageType::kMessageTypePause).send();
  381. }
  382. }
  383. SpircCommand::Prev => {
  384. if active {
  385. self.handle_prev();
  386. self.notify(None);
  387. } else {
  388. CommandSender::new(self, MessageType::kMessageTypePrev).send();
  389. }
  390. }
  391. SpircCommand::Next => {
  392. if active {
  393. self.handle_next();
  394. self.notify(None);
  395. } else {
  396. CommandSender::new(self, MessageType::kMessageTypeNext).send();
  397. }
  398. }
  399. SpircCommand::VolumeUp => {
  400. if active {
  401. self.handle_volume_up();
  402. self.notify(None);
  403. } else {
  404. CommandSender::new(self, MessageType::kMessageTypeVolumeUp).send();
  405. }
  406. }
  407. SpircCommand::VolumeDown => {
  408. if active {
  409. self.handle_volume_down();
  410. self.notify(None);
  411. } else {
  412. CommandSender::new(self, MessageType::kMessageTypeVolumeDown).send();
  413. }
  414. }
  415. SpircCommand::Shutdown => {
  416. CommandSender::new(self, MessageType::kMessageTypeGoodbye).send();
  417. self.shutdown = true;
  418. self.commands.close();
  419. }
  420. }
  421. }
  422. fn handle_frame(&mut self, frame: Frame) {
  423. debug!(
  424. "{:?} {:?} {} {} {}",
  425. frame.get_typ(),
  426. frame.get_device_state().get_name(),
  427. frame.get_ident(),
  428. frame.get_seq_nr(),
  429. frame.get_state_update_id()
  430. );
  431. if frame.get_ident() == self.ident
  432. || (frame.get_recipient().len() > 0 && !frame.get_recipient().contains(&self.ident))
  433. {
  434. return;
  435. }
  436. match frame.get_typ() {
  437. MessageType::kMessageTypeHello => {
  438. self.notify(Some(frame.get_ident()));
  439. }
  440. MessageType::kMessageTypeLoad => {
  441. if !self.device.get_is_active() {
  442. let now = self.now_ms();
  443. self.device.set_is_active(true);
  444. self.device.set_became_active_at(now);
  445. }
  446. self.update_tracks(&frame);
  447. if self.state.get_track().len() > 0 {
  448. let now = self.now_ms();
  449. self.state.set_position_ms(frame.get_state().get_position_ms());
  450. self.state.set_position_measured_at(now as u64);
  451. let play = frame.get_state().get_status() == PlayStatus::kPlayStatusPlay;
  452. self.load_track(play);
  453. } else {
  454. info!("No more tracks left in queue");
  455. self.state.set_status(PlayStatus::kPlayStatusStop);
  456. }
  457. self.notify(None);
  458. }
  459. MessageType::kMessageTypePlay => {
  460. self.handle_play();
  461. self.notify(None);
  462. }
  463. MessageType::kMessageTypePlayPause => {
  464. self.handle_play_pause();
  465. self.notify(None);
  466. }
  467. MessageType::kMessageTypePause => {
  468. self.handle_pause();
  469. self.notify(None);
  470. }
  471. MessageType::kMessageTypeNext => {
  472. self.handle_next();
  473. self.notify(None);
  474. }
  475. MessageType::kMessageTypePrev => {
  476. self.handle_prev();
  477. self.notify(None);
  478. }
  479. MessageType::kMessageTypeVolumeUp => {
  480. self.handle_volume_up();
  481. self.notify(None);
  482. }
  483. MessageType::kMessageTypeVolumeDown => {
  484. self.handle_volume_down();
  485. self.notify(None);
  486. }
  487. MessageType::kMessageTypeRepeat => {
  488. self.state.set_repeat(frame.get_state().get_repeat());
  489. self.notify(None);
  490. }
  491. MessageType::kMessageTypeShuffle => {
  492. self.state.set_shuffle(frame.get_state().get_shuffle());
  493. if self.state.get_shuffle() {
  494. let current_index = self.state.get_playing_track_index();
  495. {
  496. let tracks = self.state.mut_track();
  497. tracks.swap(0, current_index as usize);
  498. if let Some((_, rest)) = tracks.split_first_mut() {
  499. let mut rng = rand::thread_rng();
  500. rest.shuffle(&mut rng);
  501. }
  502. }
  503. self.state.set_playing_track_index(0);
  504. } else {
  505. let context = self.state.get_context_uri();
  506. debug!("{:?}", context);
  507. }
  508. self.notify(None);
  509. }
  510. MessageType::kMessageTypeSeek => {
  511. let position = frame.get_position();
  512. let now = self.now_ms();
  513. self.state.set_position_ms(position);
  514. self.state.set_position_measured_at(now as u64);
  515. self.player.seek(position);
  516. self.notify(None);
  517. }
  518. MessageType::kMessageTypeReplace => {
  519. self.update_tracks(&frame);
  520. self.notify(None);
  521. }
  522. MessageType::kMessageTypeVolume => {
  523. self.set_volume(frame.get_volume() as u16);
  524. self.notify(None);
  525. }
  526. MessageType::kMessageTypeNotify => {
  527. if self.device.get_is_active() && frame.get_device_state().get_is_active() {
  528. self.device.set_is_active(false);
  529. self.state.set_status(PlayStatus::kPlayStatusStop);
  530. self.player.stop();
  531. self.mixer.stop();
  532. }
  533. }
  534. _ => (),
  535. }
  536. }
  537. fn handle_play(&mut self) {
  538. if self.state.get_status() == PlayStatus::kPlayStatusPause {
  539. self.mixer.start();
  540. self.player.play();
  541. self.state.set_status(PlayStatus::kPlayStatusPlay);
  542. let now = self.now_ms();
  543. self.state.set_position_measured_at(now as u64);
  544. }
  545. }
  546. fn handle_play_pause(&mut self) {
  547. match self.state.get_status() {
  548. PlayStatus::kPlayStatusPlay => self.handle_pause(),
  549. PlayStatus::kPlayStatusPause => self.handle_play(),
  550. _ => (),
  551. }
  552. }
  553. fn handle_pause(&mut self) {
  554. if self.state.get_status() == PlayStatus::kPlayStatusPlay {
  555. self.player.pause();
  556. self.mixer.stop();
  557. self.state.set_status(PlayStatus::kPlayStatusPause);
  558. let now = self.now_ms() as u64;
  559. let position = self.state.get_position_ms();
  560. let diff = now - self.state.get_position_measured_at();
  561. self.state.set_position_ms(position + diff as u32);
  562. self.state.set_position_measured_at(now);
  563. }
  564. }
  565. fn consume_queued_track(&mut self) -> usize {
  566. // Removes current track if it is queued
  567. // Returns the index of the next track
  568. let current_index = self.state.get_playing_track_index() as usize;
  569. if self.state.get_track()[current_index].get_queued() {
  570. self.state.mut_track().remove(current_index);
  571. return current_index;
  572. }
  573. current_index + 1
  574. }
  575. fn handle_next(&mut self) {
  576. let mut new_index = self.consume_queued_track() as u32;
  577. let mut continue_playing = true;
  578. debug!(
  579. "At track {:?} of {:?} <{:?}> update [{}]",
  580. new_index,
  581. self.state.get_track().len(),
  582. self.state.get_context_uri(),
  583. self.state.get_track().len() as u32 - new_index < CONTEXT_FETCH_THRESHOLD
  584. );
  585. let context_uri = self.state.get_context_uri().to_owned();
  586. if (context_uri.starts_with("spotify:station:") || context_uri.starts_with("spotify:dailymix:"))
  587. && ((self.state.get_track().len() as u32) - new_index) < CONTEXT_FETCH_THRESHOLD
  588. {
  589. self.context_fut = self.resolve_station(&context_uri);
  590. self.update_tracks_from_context();
  591. }
  592. if new_index >= self.state.get_track().len() as u32 {
  593. new_index = 0; // Loop around back to start
  594. continue_playing = self.state.get_repeat();
  595. }
  596. self.state.set_playing_track_index(new_index);
  597. self.state.set_position_ms(0);
  598. let now = self.now_ms();
  599. self.state.set_position_measured_at(now as u64);
  600. self.load_track(continue_playing);
  601. }
  602. fn handle_prev(&mut self) {
  603. // Previous behaves differently based on the position
  604. // Under 3s it goes to the previous song (starts playing)
  605. // Over 3s it seeks to zero (retains previous play status)
  606. if self.position() < 3000 {
  607. // Queued tracks always follow the currently playing track.
  608. // They should not be considered when calculating the previous
  609. // track so extract them beforehand and reinsert them after it.
  610. let mut queue_tracks = Vec::new();
  611. {
  612. let queue_index = self.consume_queued_track();
  613. let tracks = self.state.mut_track();
  614. while queue_index < tracks.len() && tracks[queue_index].get_queued() {
  615. queue_tracks.push(tracks.remove(queue_index));
  616. }
  617. }
  618. let current_index = self.state.get_playing_track_index();
  619. let new_index = if current_index > 0 {
  620. current_index - 1
  621. } else if self.state.get_repeat() {
  622. self.state.get_track().len() as u32 - 1
  623. } else {
  624. 0
  625. };
  626. // Reinsert queued tracks after the new playing track.
  627. let mut pos = (new_index + 1) as usize;
  628. for track in queue_tracks.into_iter() {
  629. self.state.mut_track().insert(pos, track);
  630. pos += 1;
  631. }
  632. let now = self.now_ms();
  633. self.state.set_playing_track_index(new_index);
  634. self.state.set_position_ms(0);
  635. self.state.set_position_measured_at(now as u64);
  636. self.load_track(true);
  637. } else {
  638. let now = self.now_ms();
  639. self.state.set_position_ms(0);
  640. self.state.set_position_measured_at(now as u64);
  641. self.player.seek(0);
  642. }
  643. }
  644. fn handle_volume_up(&mut self) {
  645. let mut volume: u32 = self.device.get_volume() as u32 + 4096;
  646. if volume > 0xFFFF {
  647. volume = 0xFFFF;
  648. }
  649. self.set_volume(volume as u16);
  650. }
  651. fn handle_volume_down(&mut self) {
  652. let mut volume: i32 = self.device.get_volume() as i32 - 4096;
  653. if volume < 0 {
  654. volume = 0;
  655. }
  656. self.set_volume(volume as u16);
  657. }
  658. fn handle_end_of_track(&mut self) {
  659. self.handle_next();
  660. self.notify(None);
  661. }
  662. fn position(&mut self) -> u32 {
  663. let diff = self.now_ms() as u64 - self.state.get_position_measured_at();
  664. self.state.get_position_ms() + diff as u32
  665. }
  666. fn resolve_station(&self, uri: &str) -> Box<Future<Item = serde_json::Value, Error = MercuryError>> {
  667. let radio_uri = format!("hm://radio-apollo/v3/stations/{}", uri);
  668. self.resolve_uri(&radio_uri)
  669. }
  670. fn resolve_uri(&self, uri: &str) -> Box<Future<Item = serde_json::Value, Error = MercuryError>> {
  671. let request = self.session.mercury().get(uri);
  672. Box::new(request.and_then(move |response| {
  673. let data = response.payload.first().expect("Empty payload on context uri");
  674. let response: serde_json::Value = serde_json::from_slice(&data).unwrap();
  675. Ok(response)
  676. }))
  677. }
  678. fn update_tracks_from_context(&mut self) {
  679. if let Some(ref context) = self.context {
  680. self.context_fut = self.resolve_uri(&context.next_page_url);
  681. let new_tracks = &context.tracks;
  682. debug!("Adding {:?} tracks from context to frame", new_tracks.len());
  683. let mut track_vec = self.state.take_track().into_vec();
  684. if let Some(head) = track_vec.len().checked_sub(CONTEXT_TRACKS_HISTORY) {
  685. track_vec.drain(0..head);
  686. }
  687. track_vec.extend_from_slice(&new_tracks);
  688. self.state.set_track(protobuf::RepeatedField::from_vec(track_vec));
  689. // Update playing index
  690. if let Some(new_index) = self
  691. .state
  692. .get_playing_track_index()
  693. .checked_sub(CONTEXT_TRACKS_HISTORY as u32)
  694. {
  695. self.state.set_playing_track_index(new_index);
  696. }
  697. }
  698. }
  699. fn update_tracks(&mut self, frame: &protocol::spirc::Frame) {
  700. let index = frame.get_state().get_playing_track_index();
  701. let context_uri = frame.get_state().get_context_uri().to_owned();
  702. let tracks = frame.get_state().get_track();
  703. debug!("Frame has {:?} tracks", tracks.len());
  704. if context_uri.starts_with("spotify:station:") || context_uri.starts_with("spotify:dailymix:") {
  705. self.context_fut = self.resolve_station(&context_uri);
  706. }
  707. self.state.set_playing_track_index(index);
  708. self.state.set_track(tracks.into_iter().cloned().collect());
  709. self.state.set_context_uri(context_uri);
  710. self.state.set_repeat(frame.get_state().get_repeat());
  711. self.state.set_shuffle(frame.get_state().get_shuffle());
  712. }
  713. fn load_track(&mut self, play: bool) {
  714. let track = {
  715. let mut index = self.state.get_playing_track_index();
  716. // Check for malformed gid
  717. let tracks_len = self.state.get_track().len() as u32;
  718. let mut track_ref = &self.state.get_track()[index as usize];
  719. while track_ref.get_gid().len() != 16 {
  720. warn!(
  721. "Skipping track {:?} at position [{}] of {}",
  722. track_ref.get_uri(),
  723. index,
  724. tracks_len
  725. );
  726. index = if index + 1 < tracks_len { index + 1 } else { 0 };
  727. track_ref = &self.state.get_track()[index as usize];
  728. }
  729. SpotifyId::from_raw(track_ref.get_gid()).unwrap()
  730. };
  731. let position = self.state.get_position_ms();
  732. let end_of_track = self.player.load(track, play, position);
  733. if play {
  734. self.state.set_status(PlayStatus::kPlayStatusPlay);
  735. } else {
  736. self.state.set_status(PlayStatus::kPlayStatusPause);
  737. }
  738. self.end_of_track = Box::new(end_of_track);
  739. }
  740. fn hello(&mut self) {
  741. CommandSender::new(self, MessageType::kMessageTypeHello).send();
  742. }
  743. fn notify(&mut self, recipient: Option<&str>) {
  744. let mut cs = CommandSender::new(self, MessageType::kMessageTypeNotify);
  745. if let Some(s) = recipient {
  746. cs = cs.recipient(&s);
  747. }
  748. cs.send();
  749. }
  750. fn set_volume(&mut self, volume: u16) {
  751. self.device.set_volume(volume as u32);
  752. self.mixer.set_volume(volume_to_mixer(volume, self.linear_volume));
  753. if let Some(cache) = self.session.cache() {
  754. cache.save_volume(Volume { volume })
  755. }
  756. }
  757. }
  758. impl Drop for SpircTask {
  759. fn drop(&mut self) {
  760. debug!("drop Spirc[{}]", self.session.session_id());
  761. }
  762. }
  763. struct CommandSender<'a> {
  764. spirc: &'a mut SpircTask,
  765. frame: protocol::spirc::Frame,
  766. }
  767. impl<'a> CommandSender<'a> {
  768. fn new(spirc: &'a mut SpircTask, cmd: MessageType) -> CommandSender {
  769. let mut frame = protocol::spirc::Frame::new();
  770. frame.set_version(1);
  771. frame.set_protocol_version(::std::convert::Into::into("2.0.0"));
  772. frame.set_ident(spirc.ident.clone());
  773. frame.set_seq_nr(spirc.sequence.get());
  774. frame.set_typ(cmd);
  775. frame.set_device_state(spirc.device.clone());
  776. frame.set_state_update_id(spirc.now_ms());
  777. CommandSender {
  778. spirc: spirc,
  779. frame: frame,
  780. }
  781. }
  782. fn recipient(mut self, recipient: &'a str) -> CommandSender {
  783. self.frame.mut_recipient().push(recipient.to_owned());
  784. self
  785. }
  786. #[allow(dead_code)]
  787. fn state(mut self, state: protocol::spirc::State) -> CommandSender<'a> {
  788. self.frame.set_state(state);
  789. self
  790. }
  791. fn send(mut self) {
  792. if !self.frame.has_state() && self.spirc.device.get_is_active() {
  793. self.frame.set_state(self.spirc.state.clone());
  794. }
  795. let send = self.spirc.sender.start_send(self.frame).unwrap();
  796. assert!(send.is_ready());
  797. }
  798. }