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/queue.h>
30 #include <mpd/send.h>
31 #include <mpd/recv.h>
32 #include <mpd/pair.h>
33 #include <mpd/response.h>
34 #include <mpd/song.h>
35 #include "internal.h"
36 #include "isend.h"
37 #include "run.h"
38
39 #include <limits.h>
40 #include <stdio.h>
41 #include <stdlib.h>
42
43 bool
mpd_send_list_queue_meta(struct mpd_connection * connection)44 mpd_send_list_queue_meta(struct mpd_connection *connection)
45 {
46 return mpd_send_command(connection, "playlistinfo", NULL);
47 }
48
49 bool
mpd_send_list_queue_range_meta(struct mpd_connection * connection,unsigned start,unsigned end)50 mpd_send_list_queue_range_meta(struct mpd_connection *connection,
51 unsigned start, unsigned end)
52 {
53 return mpd_send_range_command(connection, "playlistinfo", start, end);
54 }
55
56 bool
mpd_send_get_queue_song_pos(struct mpd_connection * connection,unsigned pos)57 mpd_send_get_queue_song_pos(struct mpd_connection *connection, unsigned pos)
58 {
59 return mpd_send_int_command(connection, "playlistinfo", pos);
60 }
61
62 struct mpd_song *
mpd_run_get_queue_song_pos(struct mpd_connection * connection,unsigned pos)63 mpd_run_get_queue_song_pos(struct mpd_connection *connection, unsigned pos)
64 {
65 struct mpd_song *song;
66
67 if (!mpd_run_check(connection) ||
68 !mpd_send_get_queue_song_pos(connection, pos))
69 return NULL;
70
71 song = mpd_recv_song(connection);
72 if (!mpd_response_finish(connection) && song != NULL) {
73 mpd_song_free(song);
74 return NULL;
75 }
76
77 return song;
78
79 }
80
81 bool
mpd_send_get_queue_song_id(struct mpd_connection * connection,unsigned id)82 mpd_send_get_queue_song_id(struct mpd_connection *connection, unsigned id)
83 {
84 return mpd_send_int_command(connection, "playlistid", id);
85 }
86
87 struct mpd_song *
mpd_run_get_queue_song_id(struct mpd_connection * connection,unsigned id)88 mpd_run_get_queue_song_id(struct mpd_connection *connection, unsigned id)
89 {
90 struct mpd_song *song;
91
92 if (!mpd_run_check(connection) ||
93 !mpd_send_get_queue_song_id(connection, id))
94 return NULL;
95
96 song = mpd_recv_song(connection);
97 if (!mpd_response_finish(connection) && song != NULL) {
98 mpd_song_free(song);
99 return NULL;
100 }
101
102 return song;
103
104 }
105
106 bool
mpd_send_queue_changes_meta(struct mpd_connection * connection,unsigned version)107 mpd_send_queue_changes_meta(struct mpd_connection *connection,
108 unsigned version)
109 {
110 return mpd_send_ll_command(connection, "plchanges", version);
111 }
112
113 bool
mpd_send_queue_changes_meta_range(struct mpd_connection * connection,unsigned version,unsigned start,unsigned end)114 mpd_send_queue_changes_meta_range(struct mpd_connection *connection,
115 unsigned version,
116 unsigned start, unsigned end)
117 {
118 return mpd_send_u_range_command(connection, "plchanges",
119 version, start, end);
120 }
121
122 bool
mpd_send_queue_changes_brief(struct mpd_connection * connection,unsigned version)123 mpd_send_queue_changes_brief(struct mpd_connection *connection,
124 unsigned version)
125 {
126 return mpd_send_ll_command(connection, "plchangesposid", version);
127 }
128
129 bool
mpd_send_queue_changes_brief_range(struct mpd_connection * connection,unsigned version,unsigned start,unsigned end)130 mpd_send_queue_changes_brief_range(struct mpd_connection *connection,
131 unsigned version,
132 unsigned start, unsigned end)
133 {
134 return mpd_send_u_range_command(connection, "plchangesposid",
135 version, start, end);
136 }
137
138 bool
mpd_recv_queue_change_brief(struct mpd_connection * connection,unsigned * position_r,unsigned * id_r)139 mpd_recv_queue_change_brief(struct mpd_connection *connection,
140 unsigned *position_r, unsigned *id_r)
141 {
142 struct mpd_pair *pair;
143
144 pair = mpd_recv_pair_named(connection, "cpos");
145 if (pair == NULL)
146 return false;
147
148 *position_r = atoi(pair->value);
149 mpd_return_pair(connection, pair);
150
151 pair = mpd_recv_pair_named(connection, "Id");
152 if (pair == NULL) {
153 mpd_return_pair(connection, pair);
154
155 if (!mpd_error_is_defined(&connection->error)) {
156 mpd_error_code(&connection->error,
157 MPD_ERROR_MALFORMED);
158 mpd_error_message(&connection->error,
159 "No id received");
160 }
161
162 return false;
163 }
164
165 *id_r = atoi(pair->value);
166 mpd_return_pair(connection, pair);
167
168 return !mpd_error_is_defined(&connection->error);
169 }
170
171 bool
mpd_send_add(struct mpd_connection * connection,const char * uri)172 mpd_send_add(struct mpd_connection *connection, const char *uri)
173 {
174 return mpd_send_command(connection, "add", uri, NULL);
175 }
176
177 bool
mpd_run_add(struct mpd_connection * connection,const char * uri)178 mpd_run_add(struct mpd_connection *connection, const char *uri)
179 {
180 return mpd_run_check(connection) &&
181 mpd_send_add(connection, uri) &&
182 mpd_response_finish(connection);
183 }
184
185 bool
mpd_send_add_whence(struct mpd_connection * connection,const char * uri,unsigned to,enum mpd_position_whence whence)186 mpd_send_add_whence(struct mpd_connection *connection, const char *uri,
187 unsigned to, enum mpd_position_whence whence)
188 {
189 const char *whence_s = mpd_position_whence_char(whence);
190
191 char to_str[64] = "";
192 snprintf(to_str, 64, "%s%u", whence_s, to);
193
194 return mpd_send_s_s_command(connection, "add", uri, to_str);
195 }
196
197 bool
mpd_run_add_whence(struct mpd_connection * connection,const char * uri,unsigned to,enum mpd_position_whence whence)198 mpd_run_add_whence(struct mpd_connection *connection, const char *uri,
199 unsigned to, enum mpd_position_whence whence)
200 {
201 return mpd_run_check(connection) &&
202 mpd_send_add_whence(connection, uri, to, whence) &&
203 mpd_response_finish(connection);
204 }
205
206 bool
mpd_send_add_id(struct mpd_connection * connection,const char * uri)207 mpd_send_add_id(struct mpd_connection *connection, const char *uri)
208 {
209 return mpd_send_command(connection, "addid", uri, NULL);
210 }
211
212 bool
mpd_send_add_id_to(struct mpd_connection * connection,const char * uri,unsigned to)213 mpd_send_add_id_to(struct mpd_connection *connection, const char *uri,
214 unsigned to)
215 {
216 return mpd_send_s_u_command(connection, "addid", uri, to);
217 }
218
219 bool
mpd_send_add_id_whence(struct mpd_connection * connection,const char * uri,unsigned to,enum mpd_position_whence whence)220 mpd_send_add_id_whence(struct mpd_connection *connection, const char *uri,
221 unsigned to, enum mpd_position_whence whence)
222 {
223 const char *whence_s = mpd_position_whence_char(whence);
224
225 char to_str[64] = "";
226 snprintf(to_str, 64, "%s%u", whence_s, to);
227
228 return mpd_send_s_s_command(connection, "addid", uri, to_str);
229 }
230
231 int
mpd_recv_song_id(struct mpd_connection * connection)232 mpd_recv_song_id(struct mpd_connection *connection)
233 {
234 struct mpd_pair *pair;
235 int id = -1;
236
237 pair = mpd_recv_pair_named(connection, "Id");
238 if (pair != NULL) {
239 id = atoi(pair->value);
240 mpd_return_pair(connection, pair);
241 }
242
243 return id;
244 }
245
246 int
mpd_run_add_id(struct mpd_connection * connection,const char * uri)247 mpd_run_add_id(struct mpd_connection *connection, const char *uri)
248 {
249 int id;
250
251 if (!mpd_run_check(connection) ||
252 !mpd_send_add_id(connection, uri))
253 return -1;
254
255 id = mpd_recv_song_id(connection);
256
257 if (!mpd_response_finish(connection))
258 id = -1;
259
260 return id;
261 }
262
263 int
mpd_run_add_id_to(struct mpd_connection * connection,const char * uri,unsigned to)264 mpd_run_add_id_to(struct mpd_connection *connection, const char *uri,
265 unsigned to)
266 {
267 int id;
268
269 if (!mpd_run_check(connection) ||
270 !mpd_send_add_id_to(connection, uri, to))
271 return -1;
272
273 id = mpd_recv_song_id(connection);
274
275 if (!mpd_response_finish(connection))
276 id = -1;
277
278 return id;
279 }
280
281 int
mpd_run_add_id_whence(struct mpd_connection * connection,const char * uri,unsigned to,enum mpd_position_whence whence)282 mpd_run_add_id_whence(struct mpd_connection *connection, const char *uri,
283 unsigned to, enum mpd_position_whence whence)
284 {
285 int id;
286
287 if (!mpd_run_check(connection) ||
288 !mpd_send_add_id_whence(connection, uri, to, whence))
289 return -1;
290
291 id = mpd_recv_song_id(connection);
292
293 if (!mpd_response_finish(connection))
294 id = -1;
295
296 return id;
297 }
298
299 bool
mpd_send_delete(struct mpd_connection * connection,unsigned pos)300 mpd_send_delete(struct mpd_connection *connection, unsigned pos)
301 {
302 return mpd_send_int_command(connection, "delete", pos);
303 }
304
305 bool
mpd_run_delete(struct mpd_connection * connection,unsigned pos)306 mpd_run_delete(struct mpd_connection *connection, unsigned pos)
307 {
308 return mpd_run_check(connection) &&
309 mpd_send_delete(connection, pos) &&
310 mpd_response_finish(connection);
311 }
312
313 bool
mpd_send_delete_range(struct mpd_connection * connection,unsigned start,unsigned end)314 mpd_send_delete_range(struct mpd_connection *connection,
315 unsigned start, unsigned end)
316 {
317 return mpd_send_range_command(connection, "delete", start, end);
318 }
319
320 bool
mpd_run_delete_range(struct mpd_connection * connection,unsigned start,unsigned end)321 mpd_run_delete_range(struct mpd_connection *connection,
322 unsigned start, unsigned end)
323 {
324 return mpd_run_check(connection) &&
325 mpd_send_delete_range(connection, start, end) &&
326 mpd_response_finish(connection);
327 }
328
329 bool
mpd_send_delete_id(struct mpd_connection * connection,unsigned id)330 mpd_send_delete_id(struct mpd_connection *connection, unsigned id)
331 {
332 return mpd_send_int_command(connection, "deleteid", id);
333 }
334
335 bool
mpd_run_delete_id(struct mpd_connection * connection,unsigned id)336 mpd_run_delete_id(struct mpd_connection *connection, unsigned id)
337 {
338 return mpd_run_check(connection) &&
339 mpd_send_delete_id(connection, id) &&
340 mpd_response_finish(connection);
341 }
342
343 bool
mpd_send_shuffle(struct mpd_connection * connection)344 mpd_send_shuffle(struct mpd_connection *connection)
345 {
346 return mpd_send_command(connection, "shuffle", NULL);
347 }
348
349 bool
mpd_run_shuffle(struct mpd_connection * connection)350 mpd_run_shuffle(struct mpd_connection *connection)
351 {
352 return mpd_run_check(connection) &&
353 mpd_send_shuffle(connection) &&
354 mpd_response_finish(connection);
355 }
356
357 bool
mpd_send_shuffle_range(struct mpd_connection * connection,unsigned start,unsigned end)358 mpd_send_shuffle_range(struct mpd_connection *connection, unsigned start, unsigned end)
359 {
360 return mpd_send_range_command(connection, "shuffle", start, end);
361 }
362
363 bool
mpd_run_shuffle_range(struct mpd_connection * connection,unsigned start,unsigned end)364 mpd_run_shuffle_range(struct mpd_connection *connection,
365 unsigned start, unsigned end)
366 {
367 return mpd_run_check(connection) &&
368 mpd_send_shuffle_range(connection, start, end) &&
369 mpd_response_finish(connection);
370 }
371
372 bool
mpd_send_clear(struct mpd_connection * connection)373 mpd_send_clear(struct mpd_connection *connection)
374 {
375 return mpd_send_command(connection, "clear", NULL);
376 }
377
378 bool
mpd_run_clear(struct mpd_connection * connection)379 mpd_run_clear(struct mpd_connection *connection)
380 {
381 return mpd_run_check(connection) &&
382 mpd_send_clear(connection) &&
383 mpd_response_finish(connection);
384 }
385
386 bool
mpd_send_move(struct mpd_connection * connection,unsigned from,unsigned to)387 mpd_send_move(struct mpd_connection *connection, unsigned from, unsigned to)
388 {
389 return mpd_send_int2_command(connection, "move", from, to);
390 }
391
392 bool
mpd_run_move(struct mpd_connection * connection,unsigned from,unsigned to)393 mpd_run_move(struct mpd_connection *connection, unsigned from, unsigned to)
394 {
395 return mpd_run_check(connection) &&
396 mpd_send_move(connection, from, to) &&
397 mpd_response_finish(connection);
398 }
399
400 bool
mpd_send_move_id(struct mpd_connection * connection,unsigned from,unsigned to)401 mpd_send_move_id(struct mpd_connection *connection, unsigned from, unsigned to)
402 {
403 return mpd_send_int2_command(connection, "moveid", from, to);
404 }
405
406 bool
mpd_run_move_id(struct mpd_connection * connection,unsigned from,unsigned to)407 mpd_run_move_id(struct mpd_connection *connection, unsigned from, unsigned to)
408 {
409 return mpd_run_check(connection) &&
410 mpd_send_move_id(connection, from, to) &&
411 mpd_response_finish(connection);
412 }
413
414 bool
mpd_send_move_range(struct mpd_connection * connection,unsigned start,unsigned end,unsigned to)415 mpd_send_move_range(struct mpd_connection *connection,
416 unsigned start, unsigned end, unsigned to)
417 {
418 return mpd_send_range_u_command(connection, "move", start, end, to);
419 }
420
421 bool
mpd_run_move_range(struct mpd_connection * connection,unsigned start,unsigned end,unsigned to)422 mpd_run_move_range(struct mpd_connection *connection,
423 unsigned start, unsigned end, unsigned to)
424 {
425 return mpd_run_check(connection) &&
426 mpd_send_move_range(connection, start, end, to) &&
427 mpd_response_finish(connection);
428 }
429
430 bool
mpd_send_swap(struct mpd_connection * connection,unsigned pos1,unsigned pos2)431 mpd_send_swap(struct mpd_connection *connection, unsigned pos1, unsigned pos2)
432 {
433 return mpd_send_int2_command(connection, "swap", pos1, pos2);
434 }
435
436 bool
mpd_run_swap(struct mpd_connection * connection,unsigned pos1,unsigned pos2)437 mpd_run_swap(struct mpd_connection *connection, unsigned pos1, unsigned pos2)
438 {
439 return mpd_run_check(connection) &&
440 mpd_send_swap(connection, pos1, pos2) &&
441 mpd_response_finish(connection);
442 }
443
444 bool
mpd_send_swap_id(struct mpd_connection * connection,unsigned id1,unsigned id2)445 mpd_send_swap_id(struct mpd_connection *connection, unsigned id1, unsigned id2)
446 {
447 return mpd_send_int2_command(connection, "swapid", id1, id2);
448 }
449
450 bool
mpd_run_swap_id(struct mpd_connection * connection,unsigned id1,unsigned id2)451 mpd_run_swap_id(struct mpd_connection *connection, unsigned id1, unsigned id2)
452 {
453 return mpd_run_check(connection) &&
454 mpd_send_swap_id(connection, id1, id2) &&
455 mpd_response_finish(connection);
456 }
457
458 bool
mpd_send_add_tag_id(struct mpd_connection * connection,unsigned id,enum mpd_tag_type tag,const char * value)459 mpd_send_add_tag_id(struct mpd_connection *connection, unsigned id,
460 enum mpd_tag_type tag, const char *value)
461 {
462 return mpd_send_u_s_s_command(connection, "addtagid",
463 id, mpd_tag_name(tag), value);
464 }
465
466 bool
mpd_run_add_tag_id(struct mpd_connection * connection,unsigned id,enum mpd_tag_type tag,const char * value)467 mpd_run_add_tag_id(struct mpd_connection *connection, unsigned id,
468 enum mpd_tag_type tag, const char *value)
469 {
470 return mpd_run_check(connection) &&
471 mpd_send_add_tag_id(connection, id, tag, value) &&
472 mpd_response_finish(connection);
473 }
474
475 bool
mpd_send_clear_tag_id(struct mpd_connection * connection,unsigned id,enum mpd_tag_type tag)476 mpd_send_clear_tag_id(struct mpd_connection *connection, unsigned id,
477 enum mpd_tag_type tag)
478 {
479 return mpd_send_u_s_command(connection, "cleartagid",
480 id, mpd_tag_name(tag));
481 }
482
483 bool
mpd_run_clear_tag_id(struct mpd_connection * connection,unsigned id,enum mpd_tag_type tag)484 mpd_run_clear_tag_id(struct mpd_connection *connection, unsigned id,
485 enum mpd_tag_type tag)
486 {
487 return mpd_run_check(connection) &&
488 mpd_send_clear_tag_id(connection, id, tag) &&
489 mpd_response_finish(connection);
490 }
491
492 bool
mpd_send_clear_all_tags_id(struct mpd_connection * connection,unsigned id)493 mpd_send_clear_all_tags_id(struct mpd_connection *connection, unsigned id)
494 {
495 return mpd_send_int_command(connection, "cleartagid", id);
496 }
497
498 bool
mpd_run_clear_all_tags_id(struct mpd_connection * connection,unsigned id)499 mpd_run_clear_all_tags_id(struct mpd_connection *connection, unsigned id)
500 {
501 return mpd_run_check(connection) &&
502 mpd_send_clear_all_tags_id(connection, id) &&
503 mpd_response_finish(connection);
504 }
505
506 bool
mpd_send_prio(struct mpd_connection * connection,unsigned priority,unsigned position)507 mpd_send_prio(struct mpd_connection *connection, unsigned priority,
508 unsigned position)
509 {
510 return mpd_send_int2_command(connection, "prio", priority, position);
511 }
512
513 bool
mpd_run_prio(struct mpd_connection * connection,unsigned priority,unsigned position)514 mpd_run_prio(struct mpd_connection *connection, unsigned priority,
515 unsigned position)
516 {
517 return mpd_run_check(connection) &&
518 mpd_send_prio(connection, priority, position) &&
519 mpd_response_finish(connection);
520 }
521
522 bool
mpd_send_prio_range(struct mpd_connection * connection,unsigned priority,unsigned start,unsigned end)523 mpd_send_prio_range(struct mpd_connection *connection, unsigned priority,
524 unsigned start, unsigned end)
525 {
526 return mpd_send_i_range_command(connection, "prio", priority,
527 start, end);
528 }
529
530 bool
mpd_run_prio_range(struct mpd_connection * connection,unsigned priority,unsigned start,unsigned end)531 mpd_run_prio_range(struct mpd_connection *connection, unsigned priority,
532 unsigned start, unsigned end)
533 {
534 return mpd_run_check(connection) &&
535 mpd_send_prio_range(connection, priority, start, end) &&
536 mpd_response_finish(connection);
537 }
538
539 bool
mpd_send_prio_id(struct mpd_connection * connection,unsigned priority,unsigned id)540 mpd_send_prio_id(struct mpd_connection *connection, unsigned priority,
541 unsigned id)
542 {
543 return mpd_send_int2_command(connection, "prioid", priority, id);
544 }
545
546 bool
mpd_run_prio_id(struct mpd_connection * connection,unsigned priority,unsigned id)547 mpd_run_prio_id(struct mpd_connection *connection, unsigned priority,
548 unsigned id)
549 {
550 return mpd_run_check(connection) &&
551 mpd_send_prio_id(connection, priority, id) &&
552 mpd_response_finish(connection);
553 }
554
555 bool
mpd_send_range_id(struct mpd_connection * connection,unsigned id,float start,float end)556 mpd_send_range_id(struct mpd_connection *connection, unsigned id,
557 float start, float end)
558 {
559 return mpd_send_u_frange_command(connection, "rangeid", id, start, end);
560 }
561
562 bool
mpd_run_range_id(struct mpd_connection * connection,unsigned id,float start,float end)563 mpd_run_range_id(struct mpd_connection *connection, unsigned id,
564 float start, float end)
565 {
566 return mpd_run_check(connection) &&
567 mpd_send_range_id(connection, id, start, end) &&
568 mpd_response_finish(connection);
569 }
570