1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
use mpdclient_sys::{
mpd_run_clearerror, mpd_run_consume, mpd_run_crossfade, mpd_run_mixrampdb,
mpd_run_mixrampdelay, mpd_run_next, mpd_run_pause, mpd_run_play, mpd_run_play_id,
mpd_run_play_pos, mpd_run_previous, mpd_run_random, mpd_run_repeat, mpd_run_seek_current,
mpd_run_seek_id, mpd_run_seek_id_float, mpd_run_seek_pos, mpd_run_single_state, mpd_run_stop,
mpd_send_current_song,
};
use crate::entity::EntityReceiver;
use crate::entity::Song;
use crate::entity::song::Id;
use crate::error::Result;
#[cfg(feature = "protocol_0_24")]
use super::ConsumeState;
use super::{Connection, SingleState};
#[cfg(feature = "protocol_0_24")]
use mpdclient_sys::mpd_run_consume_state;
/// Intermediate to bundle MPD player functions.
pub struct Player<'a> {
connection: &'a Connection,
}
impl<'a> Player<'a> {
pub(super) fn new(connection: &'a Connection) -> Self {
Player { connection }
}
/// Returns the current song (playing/paused).
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn current(&self) -> Result<Song> {
self.connection
.get_bool_error(|| unsafe { mpd_send_current_song(self.connection.connection()) })?;
Song::extract_one(EntityReceiver::new(self.connection))
}
/// Starts playing the current song.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn play(&self) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_play(self.connection.connection()) })
}
/// Starts playing the song from `position` in the queue.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn play_pos(&self, position: u32) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_play_pos(self.connection.connection(), position) })
}
/// Starts playing the song with `id` in the queue.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn play_id(&self, id: Id) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_play_id(self.connection.connection(), id) })
}
/// Stops playback.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn stop(&self) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_stop(self.connection.connection()) })
}
/// Pauses playback.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn pause(&self, mode: bool) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_pause(self.connection.connection(), mode) })
}
/// Plays the next song in the queue.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn next(&self) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_next(self.connection.connection()) })
}
/// Plays the previous song in the queue.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn previous(&self) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_previous(self.connection.connection()) })
}
/// Plays from `time` (in s) in the song at position `song_pos` in the queue.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn seek_pos(&self, song_pos: u32, time: u32) -> Result<()> {
self.connection.get_bool_error(|| unsafe {
mpd_run_seek_pos(self.connection.connection(), song_pos, time)
})
}
/// Plays from `time` (in s) in the song with `id` in the queue.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn seek_id(&self, id: Id, time: u32) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_seek_id(self.connection.connection(), id, time) })
}
/// Plays from `time` in the song with `id` in the queue. Accepts fractional `time` values.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn seek_id_f(&self, id: Id, time: f32) -> Result<()> {
self.connection.get_bool_error(|| unsafe {
mpd_run_seek_id_float(self.connection.connection(), id, time)
})
}
/// Plays from `time` in the current song, optionally `relative` to the current time. Accepts
/// fractional `time` values.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn seek_current(&self, time: f32, relative: bool) -> Result<()> {
self.connection.get_bool_error(|| unsafe {
mpd_run_seek_current(self.connection.connection(), time, relative)
})
}
/// Repeat the current song.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn repeat(&self, mode: bool) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_repeat(self.connection.connection(), mode) })
}
/// Randomize next song selection.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn random(&self, mode: bool) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_random(self.connection.connection(), mode) })
}
/// Sets [`SingleState`].
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn single(&self, state: SingleState) -> Result<()> {
self.connection.get_bool_error(|| unsafe {
mpd_run_single_state(self.connection.connection(), state as u32)
})
}
/// Sets consume mode. If activated, MPD removes the song from the queue after playing.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn consume_bool(&self, mode: bool) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_consume(self.connection.connection(), mode) })
}
/// Sets consume mode using extended options. If [`ConsumeState::On`], MPD removes the song from
/// the queue after playing. [`ConsumeState::Oneshot`] enables the mode for a single song, then
/// deactivates it.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
#[cfg(feature = "protocol_0_24")]
pub fn consume(&self, state: ConsumeState) -> Result<()> {
self.connection.get_bool_error(|| unsafe {
mpd_run_consume_state(self.connection.connection(), state as u32)
})
}
/// Crossfades beetween songs. Only works if song formats are the same.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn crossfade(&self, secs: u32) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_crossfade(self.connection.connection(), secs) })
}
/// Threshold at which songs will be overlapped. Doesn't fade track volume.
///
/// Tags need to be added by external tool.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn mixrampdb(&self, db: f32) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_mixrampdb(self.connection.connection(), db) })
}
/// Sets additional time subtracted from the overlap calculated by mixrampdb.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn mixrampdelay(&self, secs: f32) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_mixrampdelay(self.connection.connection(), secs) })
}
/// Clears current error in the status alternatively to starting playback. Only possible for
/// some errors.
///
/// # Errors
///
/// Returns [`Error::Mpd`](crate::Error::Mpd) if MPD returns an error.
pub fn clearerror(&self) -> Result<()> {
self.connection
.get_bool_error(|| unsafe { mpd_run_clearerror(self.connection.connection()) })
}
}