music.rs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. use std::path::Path;
  2. use std::thread;
  3. use mpd;
  4. use mpd::idle;
  5. use mpd::idle::Idle;
  6. use mpd::song::Song;
  7. use mpd::status::State;
  8. use ui::color;
  9. use ui::context::Context;
  10. use widgets::{Message, MessageSender, Update, Widget, WidgetParams};
  11. const MARGIN: u16 = 7;
  12. const WIDTH: u16 = 250;
  13. pub struct Mpd {
  14. context: Context,
  15. tx: MessageSender,
  16. state: State,
  17. song: Option<Song>
  18. }
  19. pub fn mpd(params: WidgetParams) -> Box<Widget> {
  20. let widget = Mpd {
  21. context: params.context,
  22. tx: params.tx,
  23. state: State::Stop,
  24. song: None
  25. };
  26. Box::new(widget)
  27. }
  28. impl Mpd {
  29. fn icon(&self) -> &str {
  30. match self.state {
  31. State::Play => "",
  32. State::Pause => "",
  33. State::Stop => ""
  34. }
  35. }
  36. fn get_text(&self) -> String {
  37. match self.song {
  38. Some(ref song) => match (&song.title, &song.tags.get("Artist")) {
  39. (&Some(ref title), &Some(ref artist)) => format!("{} - {}", artist, title),
  40. (&Some(ref title), &None) => title.to_string(),
  41. _ => {
  42. let path = Path::new(&song.file);
  43. let path = path.file_name().and_then(|s| s.to_str());
  44. path.unwrap_or("Unknown").to_string()
  45. }
  46. },
  47. None => "mpd".to_string()
  48. }
  49. }
  50. }
  51. impl Widget for Mpd {
  52. fn init(&mut self) {
  53. let tx = self.tx.clone();
  54. thread::spawn(move || monitor_thread(tx));
  55. }
  56. fn render(&mut self, x: u16, _w: u16) {
  57. let icon_width = self.context.measure_text(self.icon());
  58. self.context.set_bg_color(color::GREY);
  59. self.context.draw_bg(x, icon_width + MARGIN * 2);
  60. self.context.draw_text(self.icon(), x + MARGIN);
  61. let text = self.get_text();
  62. let text_width = WIDTH - MARGIN * 4 - icon_width;
  63. self.context.draw_text_with_clipping(&text, x + icon_width + MARGIN * 3, text_width);
  64. }
  65. fn width(&mut self) -> u16 {
  66. WIDTH
  67. }
  68. fn handle_event(&mut self, event: &Message) -> Update {
  69. match event {
  70. &Message::MpdEvent(ref state, ref song) => {
  71. self.state = state.clone();
  72. self.song = song.clone();
  73. Update::Rerender
  74. },
  75. &Message::MousePress(_x) => {
  76. toggle();
  77. Update::Nothing
  78. },
  79. _ => Update::Nothing
  80. }
  81. }
  82. }
  83. fn monitor_thread(tx: MessageSender) {
  84. let mut conn = mpd::client::Client::connect("127.0.0.1:6600").unwrap();
  85. loop {
  86. match (conn.status(), conn.currentsong()) {
  87. (Ok(status), Ok(song)) => {
  88. let state = status.state;
  89. let event = Message::MpdEvent(state, song);
  90. tx.send(event).expect("Failed to send mpd event");
  91. },
  92. _ => {}
  93. }
  94. conn.wait(&[idle::Subsystem::Player]).ok();
  95. }
  96. }
  97. fn toggle() {
  98. let mut conn = mpd::client::Client::connect("127.0.0.1:6600").unwrap();
  99. conn.toggle_pause().expect("Failed to pause");
  100. }