async_mpd/client/
mpdclient.rs1use async_net::{AsyncToSocketAddrs, TcpStream};
2use futures_lite::{io::BufReader, AsyncWriteExt};
3use std::net::SocketAddr;
4
5use crate::resp::WrappedResponse;
6use crate::{
7 client::resp::{
8 handlers::ResponseHandler,
9 read_resp_line,
10 respmap_handlers::{ListallResponse, ListallinfoResponse},
11 },
12 cmd::{self, MpdCmd},
13 DatabaseVersion, Error, Filter, Stats, Status, Subsystem, Track,
14};
15
16#[derive(Default)]
18pub struct MpdClient {
19 stream: Option<BufReader<TcpStream>>,
21 addr: Option<SocketAddr>,
23}
24
25impl MpdClient {
26 pub fn new() -> Self {
28 Self {
29 stream: None,
30 addr: None,
31 }
32 }
33
34 pub async fn connect<A: AsyncToSocketAddrs>(&mut self, addr: A) -> Result<String, Error> {
35 let stream = TcpStream::connect(addr).await?;
36 let sock_addr = stream.peer_addr()?;
38
39 let reader = BufReader::new(stream);
40
41 log::debug!("server: {:?}", sock_addr);
42
43 self.stream = Some(reader);
44 self.addr = Some(sock_addr);
45
46 Ok(self.read_version().await?)
48 }
49
50 pub async fn reconnect(&mut self) -> Result<(), Error> {
51 if let Some(addr) = self.addr {
52 log::debug!("Reconnection to: {:?}", addr);
53 self.connect(addr).await.map(|_| ())
54 } else {
55 log::warn!("Reconnect without previous connection");
56 Err(Error::Disconnected)
57 }
58 }
59
60 async fn read_version(&mut self) -> Result<String, Error> {
61 let br = self.stream.as_mut().ok_or(Error::Disconnected)?;
62
63 let version = read_resp_line(br).await?;
64 log::debug!("Connected: {}", version);
65 Ok(version)
66 }
67
68 pub async fn stats(&mut self) -> Result<Stats, Error> {
70 self.exec(cmd::Stats).await
71 }
72
73 pub async fn status(&mut self) -> Result<Status, Error> {
74 let status = self.exec(cmd::Status).await?;
75 Ok(status)
76 }
77
78 pub async fn update(&mut self, path: Option<&str>) -> Result<DatabaseVersion, Error> {
79 self.exec(cmd::Update(path)).await
80 }
81
82 pub async fn rescan(&mut self, path: Option<&str>) -> Result<DatabaseVersion, Error> {
83 self.exec(cmd::Rescan(path)).await
84 }
85
86 pub async fn idle(&mut self) -> Result<Subsystem, Error> {
87 self.exec(cmd::Idle).await
88 }
89
90 pub async fn noidle(&mut self) -> Result<(), Error> {
91 self.exec(cmd::NoIdle).await
92 }
93
94 pub async fn setvol(&mut self, volume: u32) -> Result<(), Error> {
95 self.exec(cmd::Setvol(volume)).await
96 }
97
98 pub async fn repeat(&mut self, repeat: bool) -> Result<(), Error> {
99 self.exec(cmd::Repeat(repeat)).await
100 }
101
102 pub async fn random(&mut self, random: bool) -> Result<(), Error> {
103 self.exec(cmd::Random(random)).await
104 }
105
106 pub async fn consume(&mut self, consume: bool) -> Result<(), Error> {
107 self.exec(cmd::Consume(consume)).await
108 }
109
110 pub async fn play(&mut self) -> Result<(), Error> {
113 self.play_pause(true).await
114 }
115
116 pub async fn playid(&mut self, id: u32) -> Result<(), Error> {
117 self.exec(cmd::PlayId(id)).await
118 }
119
120 pub async fn pause(&mut self) -> Result<(), Error> {
121 self.play_pause(false).await
122 }
123
124 pub async fn play_pause(&mut self, play: bool) -> Result<(), Error> {
125 self.exec(cmd::PlayPause(!play)).await
126 }
127
128 pub async fn next(&mut self) -> Result<(), Error> {
129 self.exec(cmd::Next).await
130 }
131
132 pub async fn prev(&mut self) -> Result<(), Error> {
133 self.exec(cmd::Prev).await
134 }
135
136 pub async fn stop(&mut self) -> Result<(), Error> {
137 self.exec(cmd::Stop).await
138 }
139
140 pub async fn listall(&mut self, path: Option<&str>) -> Result<ListallResponse, Error> {
145 self.exec(cmd::Listall(path)).await
146 }
147
148 pub async fn listallinfo(&mut self, path: Option<&str>) -> Result<ListallinfoResponse, Error> {
149 self.exec(cmd::ListallInfo(path)).await
150 }
151
152 pub async fn queue_add(&mut self, path: &str) -> Result<(), Error> {
155 self.exec(cmd::QueueAdd(path)).await
156 }
157
158 pub async fn queue_clear(&mut self) -> Result<(), Error> {
159 self.exec(cmd::QueueClear).await
160 }
161
162 pub async fn queue(&mut self) -> Result<Vec<Track>, Error> {
163 self.exec(cmd::PlaylistInfo).await
164 }
165
166 pub async fn search(&mut self, filter: &Filter) -> Result<Vec<Track>, Error> {
187 self.exec(cmd::Search(filter.to_query().as_deref())).await
188 }
189
190 pub async fn exec_wrapped<C>(&mut self, cmd: C) -> Result<WrappedResponse, crate::Error>
192 where
193 C: MpdCmd,
194 {
195 self.exec(cmd).await.map(Into::into)
196 }
197
198 pub async fn exec<C>(
200 &mut self,
201 cmd: C,
202 ) -> Result<<C::Handler as ResponseHandler>::Response, crate::Error>
203 where
204 C: MpdCmd,
205 {
206 let cmdline = cmd.to_cmdline();
207
208 self.send_command(&cmdline).await?;
209
210 let br = self.stream.as_mut().ok_or(Error::Disconnected)?;
211
212 C::Handler::handle(br).await
214 }
215
216 async fn send_command(&mut self, line: &str) -> Result<(), crate::Error> {
217 self.stream
219 .as_mut()
220 .ok_or(crate::Error::Disconnected)?
221 .get_mut()
222 .write_all(line.as_bytes())
223 .await
224 .map_err(|_| crate::Error::Disconnected)?;
225
226 Ok(())
227 }
228}