1 /* libmpdclient
2    (c) 2003-2019 The Music Player Daemon Project
3    This project's homepage is: http://www.musicpd.org
4 
5    Redistribution and use in source and binary forms, with or without
6    modification, are permitted provided that the following conditions
7    are met:
8 
9    - Redistributions of source code must retain the above copyright
10    notice, this list of conditions and the following disclaimer.
11 
12    - Redistributions in binary form must reproduce the above copyright
13    notice, this list of conditions and the following disclaimer in the
14    documentation and/or other materials provided with the distribution.
15 
16    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17    ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR
20    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28 
29 #include <mpd/player.h>
30 #include <mpd/send.h>
31 #include <mpd/song.h>
32 #include <mpd/response.h>
33 #include "isend.h"
34 #include "run.h"
35 
36 #include <limits.h>
37 #include <stdio.h>
38 
39 bool
mpd_send_current_song(struct mpd_connection * connection)40 mpd_send_current_song(struct mpd_connection *connection)
41 {
42 	return mpd_send_command(connection, "currentsong", NULL);
43 }
44 
45 struct mpd_song *
mpd_run_current_song(struct mpd_connection * connection)46 mpd_run_current_song(struct mpd_connection *connection)
47 {
48 	struct mpd_song *song;
49 
50 	if (!mpd_run_check(connection) || !mpd_send_current_song(connection))
51 		return NULL;
52 
53 	song = mpd_recv_song(connection);
54 	if (song == NULL)
55 		return NULL;
56 
57 	if (!mpd_response_finish(connection)) {
58 		mpd_song_free(song);
59 		return NULL;
60 	}
61 
62 	return song;
63 }
64 
65 bool
mpd_send_play(struct mpd_connection * connection)66 mpd_send_play(struct mpd_connection *connection)
67 {
68 	return mpd_send_command(connection, "play", NULL);
69 }
70 
71 bool
mpd_run_play(struct mpd_connection * connection)72 mpd_run_play(struct mpd_connection *connection)
73 {
74 	return mpd_run_check(connection) && mpd_send_play(connection) &&
75 		mpd_response_finish(connection);
76 }
77 
78 bool
mpd_send_play_pos(struct mpd_connection * connection,unsigned song_pos)79 mpd_send_play_pos(struct mpd_connection *connection, unsigned song_pos)
80 {
81 	return mpd_send_int_command(connection, "play", song_pos);
82 }
83 
84 bool
mpd_run_play_pos(struct mpd_connection * connection,unsigned song_pos)85 mpd_run_play_pos(struct mpd_connection *connection, unsigned song_pos)
86 {
87 	return mpd_run_check(connection) &&
88 		mpd_send_play_pos(connection, song_pos) &&
89 		mpd_response_finish(connection);
90 }
91 
92 bool
mpd_send_play_id(struct mpd_connection * connection,unsigned song_id)93 mpd_send_play_id(struct mpd_connection *connection, unsigned song_id)
94 {
95 	return mpd_send_int_command(connection, "playid", song_id);
96 }
97 
98 bool
mpd_run_play_id(struct mpd_connection * connection,unsigned song_id)99 mpd_run_play_id(struct mpd_connection *connection, unsigned song_id)
100 {
101 	return mpd_run_check(connection) &&
102 		mpd_send_play_id(connection, song_id) &&
103 		mpd_response_finish(connection);
104 }
105 
106 bool
mpd_send_stop(struct mpd_connection * connection)107 mpd_send_stop(struct mpd_connection *connection)
108 {
109 	return mpd_send_command(connection, "stop", NULL);
110 }
111 
112 bool
mpd_run_stop(struct mpd_connection * connection)113 mpd_run_stop(struct mpd_connection *connection)
114 {
115 	return mpd_run_check(connection) && mpd_send_stop(connection) &&
116 		mpd_response_finish(connection);
117 }
118 
119 bool
mpd_send_toggle_pause(struct mpd_connection * connection)120 mpd_send_toggle_pause(struct mpd_connection *connection)
121 {
122 	return mpd_send_command(connection, "pause", NULL);
123 }
124 
125 bool
mpd_run_toggle_pause(struct mpd_connection * connection)126 mpd_run_toggle_pause(struct mpd_connection *connection)
127 {
128 	return mpd_run_check(connection) &&
129 		mpd_send_toggle_pause(connection) &&
130 		mpd_response_finish(connection);
131 }
132 
133 bool
mpd_send_pause(struct mpd_connection * connection,bool mode)134 mpd_send_pause(struct mpd_connection *connection, bool mode)
135 {
136 	return mpd_send_int_command(connection, "pause", mode);
137 }
138 
139 bool
mpd_run_pause(struct mpd_connection * connection,bool mode)140 mpd_run_pause(struct mpd_connection *connection, bool mode)
141 {
142 	return mpd_run_check(connection) && mpd_send_pause(connection, mode) &&
143 		mpd_response_finish(connection);
144 }
145 
146 bool
mpd_send_next(struct mpd_connection * connection)147 mpd_send_next(struct mpd_connection *connection)
148 {
149 	return mpd_send_command(connection, "next", NULL);
150 }
151 
152 bool
mpd_run_next(struct mpd_connection * connection)153 mpd_run_next(struct mpd_connection *connection)
154 {
155 	return mpd_run_check(connection) && mpd_send_next(connection) &&
156 		mpd_response_finish(connection);
157 }
158 
159 bool
mpd_send_previous(struct mpd_connection * connection)160 mpd_send_previous(struct mpd_connection *connection)
161 {
162 	return mpd_send_command(connection, "previous", NULL);
163 }
164 
165 bool
mpd_run_previous(struct mpd_connection * connection)166 mpd_run_previous(struct mpd_connection *connection)
167 {
168 	return mpd_run_check(connection) && mpd_send_previous(connection) &&
169 		mpd_response_finish(connection);
170 }
171 
172 bool
mpd_send_seek_pos(struct mpd_connection * connection,unsigned song_pos,unsigned t)173 mpd_send_seek_pos(struct mpd_connection *connection,
174 		 unsigned song_pos, unsigned t)
175 {
176 	return mpd_send_int2_command(connection, "seek", song_pos, t);
177 }
178 
179 bool
mpd_run_seek_pos(struct mpd_connection * connection,unsigned song_pos,unsigned t)180 mpd_run_seek_pos(struct mpd_connection *connection,
181 		unsigned song_pos, unsigned t)
182 {
183 	return mpd_run_check(connection) &&
184 		mpd_send_seek_pos(connection, song_pos, t) &&
185 		mpd_response_finish(connection);
186 }
187 
188 bool
mpd_send_seek_id(struct mpd_connection * connection,unsigned song_id,unsigned t)189 mpd_send_seek_id(struct mpd_connection *connection,
190 		 unsigned song_id, unsigned t)
191 {
192 	return mpd_send_int2_command(connection, "seekid", song_id, t);
193 }
194 
195 bool
mpd_run_seek_id(struct mpd_connection * connection,unsigned song_id,unsigned t)196 mpd_run_seek_id(struct mpd_connection *connection,
197 	       unsigned song_id, unsigned t)
198 {
199 	return mpd_run_check(connection) &&
200 		mpd_send_seek_id(connection, song_id, t) &&
201 		mpd_response_finish(connection);
202 }
203 
204 bool
mpd_send_seek_id_float(struct mpd_connection * connection,unsigned song_id,float t)205 mpd_send_seek_id_float(struct mpd_connection *connection,
206 		       unsigned song_id, float t)
207 {
208 	return mpd_send_u_f_command(connection, "seekid", song_id, t);
209 }
210 
211 bool
mpd_run_seek_id_float(struct mpd_connection * connection,unsigned song_id,float t)212 mpd_run_seek_id_float(struct mpd_connection *connection,
213 		      unsigned song_id, float t)
214 {
215 	return mpd_run_check(connection) &&
216 		mpd_send_seek_id_float(connection, song_id, t) &&
217 		mpd_response_finish(connection);
218 }
219 
220 bool
mpd_send_seek_current(struct mpd_connection * connection,float t,bool relative)221 mpd_send_seek_current(struct mpd_connection *connection,
222 		      float t, bool relative)
223 {
224 	char ts[32];
225 	if (relative)
226 		snprintf(ts, sizeof(ts), "%+.3f", t);
227 	else
228 		snprintf(ts, sizeof(ts), "%.3f", t);
229 
230 	return mpd_send_command(connection, "seekcur", ts, NULL);
231 }
232 
233 bool
mpd_run_seek_current(struct mpd_connection * connection,float t,bool relative)234 mpd_run_seek_current(struct mpd_connection *connection,
235 		     float t, bool relative)
236 {
237 	return mpd_run_check(connection) &&
238 		mpd_send_seek_current(connection, t, relative) &&
239 		mpd_response_finish(connection);
240 }
241 
242 bool
mpd_send_repeat(struct mpd_connection * connection,bool mode)243 mpd_send_repeat(struct mpd_connection *connection, bool mode)
244 {
245 	return mpd_send_int_command(connection, "repeat", mode);
246 }
247 
248 bool
mpd_run_repeat(struct mpd_connection * connection,bool mode)249 mpd_run_repeat(struct mpd_connection *connection, bool mode)
250 {
251 	return mpd_run_check(connection) &&
252 		mpd_send_repeat(connection, mode) &&
253 		mpd_response_finish(connection);
254 }
255 
256 bool
mpd_send_random(struct mpd_connection * connection,bool mode)257 mpd_send_random(struct mpd_connection *connection, bool mode)
258 {
259 	return mpd_send_int_command(connection, "random", mode);
260 }
261 
262 bool
mpd_run_random(struct mpd_connection * connection,bool mode)263 mpd_run_random(struct mpd_connection *connection, bool mode)
264 {
265 	return mpd_run_check(connection) &&
266 		mpd_send_random(connection, mode) &&
267 		mpd_response_finish(connection);
268 }
269 
270 static const char *
single_state_to_string(enum mpd_single_state state)271 single_state_to_string(enum mpd_single_state state)
272 {
273 	switch (state) {
274 	case MPD_SINGLE_OFF:
275 		return "0";
276 	case MPD_SINGLE_ON:
277 		return "1";
278 	case MPD_SINGLE_ONESHOT:
279 		return "oneshot";
280 	case MPD_SINGLE_UNKNOWN:
281 		return NULL;
282 	}
283 	return NULL;
284 }
285 bool
mpd_send_single_state(struct mpd_connection * connection,enum mpd_single_state state)286 mpd_send_single_state(struct mpd_connection *connection,
287 		      enum mpd_single_state state)
288 {
289 	const char *state_str = single_state_to_string(state);
290 	if (state_str == NULL)
291 		return false;
292 
293 	return mpd_send_command(connection, "single", state_str, NULL);
294 }
295 
296 bool
mpd_run_single_state(struct mpd_connection * connection,enum mpd_single_state state)297 mpd_run_single_state(struct mpd_connection *connection,
298 		      enum mpd_single_state state)
299 {
300 	return mpd_run_check(connection) &&
301 		mpd_send_single_state(connection, state) &&
302 		mpd_response_finish(connection);
303 }
304 
305 bool
mpd_send_single(struct mpd_connection * connection,bool mode)306 mpd_send_single(struct mpd_connection *connection, bool mode)
307 {
308 	return mpd_send_int_command(connection, "single", mode);
309 }
310 
311 bool
mpd_run_single(struct mpd_connection * connection,bool mode)312 mpd_run_single(struct mpd_connection *connection, bool mode)
313 {
314 	return mpd_run_check(connection) &&
315 		mpd_send_single(connection, mode) &&
316 		mpd_response_finish(connection);
317 }
318 
319 bool
mpd_send_consume(struct mpd_connection * connection,bool mode)320 mpd_send_consume(struct mpd_connection *connection, bool mode)
321 {
322 	return mpd_send_int_command(connection, "consume", mode);
323 }
324 
325 bool
mpd_run_consume(struct mpd_connection * connection,bool mode)326 mpd_run_consume(struct mpd_connection *connection, bool mode)
327 {
328 	return mpd_run_check(connection) &&
329 		mpd_send_consume(connection, mode) &&
330 		mpd_response_finish(connection);
331 }
332 
333 bool
mpd_send_crossfade(struct mpd_connection * connection,unsigned seconds)334 mpd_send_crossfade(struct mpd_connection *connection, unsigned seconds)
335 {
336 	return mpd_send_int_command(connection, "crossfade", seconds);
337 }
338 
339 bool
mpd_run_crossfade(struct mpd_connection * connection,unsigned seconds)340 mpd_run_crossfade(struct mpd_connection *connection, unsigned seconds)
341 {
342 	return mpd_run_check(connection) &&
343 		mpd_send_crossfade(connection, seconds) &&
344 		mpd_response_finish(connection);
345 }
346 
347 bool
mpd_send_mixrampdb(struct mpd_connection * connection,float db)348 mpd_send_mixrampdb(struct mpd_connection *connection, float db)
349 {
350 	return mpd_send_float_command(connection, "mixrampdb", db);
351 }
352 
353 bool
mpd_run_mixrampdb(struct mpd_connection * connection,float db)354 mpd_run_mixrampdb(struct mpd_connection *connection, float db)
355 {
356 	return mpd_run_check(connection) &&
357 		mpd_send_mixrampdb(connection, db) &&
358 		mpd_response_finish(connection);
359 }
360 
361 bool
mpd_send_mixrampdelay(struct mpd_connection * connection,float seconds)362 mpd_send_mixrampdelay(struct mpd_connection *connection, float seconds)
363 {
364 	return mpd_send_float_command(connection, "mixrampdelay", seconds);
365 }
366 
367 bool
mpd_run_mixrampdelay(struct mpd_connection * connection,float seconds)368 mpd_run_mixrampdelay(struct mpd_connection *connection, float seconds)
369 {
370 	return mpd_run_check(connection) &&
371 		mpd_send_mixrampdelay(connection, seconds) &&
372 		mpd_response_finish(connection);
373 }
374 
375 bool
mpd_send_clearerror(struct mpd_connection * connection)376 mpd_send_clearerror(struct mpd_connection *connection)
377 {
378 	return mpd_send_command(connection, "clearerror", NULL);
379 }
380 
381 bool
mpd_run_clearerror(struct mpd_connection * connection)382 mpd_run_clearerror(struct mpd_connection *connection)
383 {
384 	return mpd_run_check(connection) && mpd_send_clearerror(connection) &&
385 		mpd_response_finish(connection);
386 }
387