1 /* libmpd (high level libmpdclient library)
2  * Copyright (C) 2004-2009 Qball Cow <qball@sarine.nl>
3  * Project homepage: http://gmpcwiki.sarine.nl/
4 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9 
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14 
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 
20 #include <stdio.h>
21 #include <stdlib.h>
22 #define __USE_GNU
23 
24 #include <string.h>
25 #include <stdarg.h>
26 #include <config.h>
27 #include "debug_printf.h"
28 #include "libmpd.h"
29 #include "libmpd-internal.h"
30 
31 
mpd_playlist_get_playlist_length(MpdObj * mi)32 int mpd_playlist_get_playlist_length(MpdObj *mi)
33 {
34 	if(!mpd_check_connected(mi))
35 	{
36 		debug_printf(DEBUG_WARNING,"not connected\n");
37 		return MPD_NOT_CONNECTED;
38 	}
39 	if(mpd_status_check(mi) != MPD_OK)
40 	{
41 		debug_printf(DEBUG_ERROR,"Failed grabbing status\n");
42 		return MPD_STATUS_FAILED;
43 	}
44 	return mi->status->playlistLength;
45 }
46 
mpd_playlist_get_old_playlist_id(MpdObj * mi)47 long long mpd_playlist_get_old_playlist_id(MpdObj *mi)
48 {
49 	return mi->OldState.playlistid;
50 }
51 
mpd_playlist_get_playlist_id(MpdObj * mi)52 long long mpd_playlist_get_playlist_id(MpdObj *mi)
53 {
54 	if(!mpd_check_connected(mi))
55 	{
56 		debug_printf(DEBUG_WARNING,"not connected\n");
57 		return MPD_NOT_CONNECTED;
58 	}
59 	if(mpd_status_check(mi) != MPD_OK)
60 	{
61 		debug_printf(DEBUG_WARNING,"Failed grabbing status\n");
62 		return MPD_STATUS_FAILED;
63 	}
64 	return mi->status->playlist;
65 }
mpd_playlist_add(MpdObj * mi,const char * path)66 int mpd_playlist_add(MpdObj *mi,const char *path)
67 {
68 	int retv = mpd_playlist_queue_add(mi, path);
69 	if(retv != MPD_OK) return retv;
70 	return mpd_playlist_queue_commit(mi);
71 }
72 
mpd_playlist_delete_id(MpdObj * mi,int songid)73 int mpd_playlist_delete_id(MpdObj *mi, int songid)
74 {
75 	int retv = mpd_playlist_queue_delete_id(mi, songid);
76 	if(retv != MPD_OK) return retv;
77 	return mpd_playlist_queue_commit(mi);
78 }
79 
mpd_playlist_delete_pos(MpdObj * mi,int songpos)80 int mpd_playlist_delete_pos(MpdObj *mi, int songpos)
81 {
82 	int retv = mpd_playlist_queue_delete_pos(mi, songpos);
83 	if(retv != MPD_OK) return retv;
84 	return mpd_playlist_queue_commit(mi);
85 }
86 /*******************************************************************************
87  * PLAYLIST
88  */
mpd_playlist_get_song(MpdObj * mi,int songid)89 mpd_Song * mpd_playlist_get_song(MpdObj *mi, int songid)
90 {
91 	mpd_Song *song = NULL;
92 	mpd_InfoEntity *ent = NULL;
93 	if(songid < 0){
94 		debug_printf(DEBUG_ERROR, "songid < 0 Failed");
95 		return NULL;
96 	}
97 	if(!mpd_check_connected(mi))
98 	{
99 		debug_printf(DEBUG_ERROR, "Not Connected\n");
100 		return NULL;
101 	}
102 
103 	if(mpd_lock_conn(mi))
104 	{
105 		return NULL;
106 	}
107 	debug_printf(DEBUG_INFO, "Trying to grab song with id: %i\n", songid);
108 	mpd_sendPlaylistIdCommand(mi->connection, songid);
109 	ent = mpd_getNextInfoEntity(mi->connection);
110 	mpd_finishCommand(mi->connection);
111 
112 	if(mpd_unlock_conn(mi))
113 	{
114 		if(ent) mpd_freeInfoEntity(ent);
115 		return NULL;
116 	}
117 
118 	if(ent == NULL)
119 	{
120 		debug_printf(DEBUG_ERROR, "Failed to grab song from mpd\n");
121 		return NULL;
122 	}
123 
124 	if(ent->type != MPD_INFO_ENTITY_TYPE_SONG)
125 	{
126 		mpd_freeInfoEntity(ent);
127 		debug_printf(DEBUG_ERROR, "Failed to grab correct song type from mpd\n");
128 		return NULL;
129 	}
130 	song = ent->info.song;
131 	ent->info.song = NULL;
132 
133 	mpd_freeInfoEntity(ent);
134 
135 	return song;
136 }
137 
mpd_playlist_get_song_from_pos(MpdObj * mi,int songpos)138 mpd_Song * mpd_playlist_get_song_from_pos(MpdObj *mi, int songpos)
139 {
140 	mpd_Song *song = NULL;
141 	mpd_InfoEntity *ent = NULL;
142 	if(songpos < 0){
143 		debug_printf(DEBUG_ERROR, "songpos < 0 Failed");
144 		return NULL;
145 	}
146 	if(!mpd_check_connected(mi))
147 	{
148 		debug_printf(DEBUG_ERROR, "Not Connected\n");
149 		return NULL;
150 	}
151 
152 	if(mpd_lock_conn(mi))
153 	{
154 		return NULL;
155 	}
156 	debug_printf(DEBUG_INFO, "Trying to grab song with id: %i\n", songpos);
157 	mpd_sendPlaylistInfoCommand(mi->connection, songpos);
158 	ent = mpd_getNextInfoEntity(mi->connection);
159 	mpd_finishCommand(mi->connection);
160 
161 	if(mpd_unlock_conn(mi))
162 	{
163 		/*TODO free entity. for now this can never happen */
164 		return NULL;
165 	}
166 
167 	if(ent == NULL)
168 	{
169 		debug_printf(DEBUG_ERROR, "Failed to grab song from mpd\n");
170 		return NULL;
171 	}
172 
173 	if(ent->type != MPD_INFO_ENTITY_TYPE_SONG)
174 	{
175 		mpd_freeInfoEntity(ent);
176 		debug_printf(DEBUG_ERROR, "Failed to grab corect song type from mpd\n");
177 		return NULL;
178 	}
179 	song = ent->info.song;
180 	ent->info.song = NULL;
181 
182 	mpd_freeInfoEntity(ent);
183 
184 	return song;
185 }
186 
mpd_playlist_get_song_from_pos_range(MpdObj * mi,int start,int stop)187 MpdData * mpd_playlist_get_song_from_pos_range(MpdObj *mi, int start, int stop)
188 {
189     MpdData *data = NULL;
190     int i;
191 	mpd_InfoEntity *ent = NULL;
192 	if(!mpd_check_connected(mi))
193 	{
194 		debug_printf(DEBUG_ERROR, "Not Connected\n");
195 		return NULL;
196 	}
197 	if(mpd_status_check(mi) != MPD_OK)
198 	{
199 		debug_printf(DEBUG_ERROR,"Failed grabbing status\n");
200 		return NULL;
201 	}
202 
203 	if(mpd_lock_conn(mi))
204 	{
205 		return NULL;
206 	}
207     /* Don't check outside playlist length */
208     if(!(stop < mi->status->playlistLength)) {
209         stop = mi->status->playlistLength -1;
210     }
211     mpd_sendCommandListBegin(mi->connection);
212     for(i=start; i <= stop; i++){
213         mpd_sendPlaylistInfoCommand(mi->connection, i);
214     }
215 	mpd_sendCommandListEnd(mi->connection);
216 	while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
217 	{
218 		if(ent->type == MPD_INFO_ENTITY_TYPE_SONG)
219 		{
220 			data = mpd_new_data_struct_append(data);
221 			data->type = MPD_DATA_TYPE_SONG;
222 			data->song = ent->info.song;
223 			ent->info.song = NULL;
224 		}
225 		mpd_freeInfoEntity(ent);
226 	}
227 	mpd_finishCommand(mi->connection);
228 
229 	if(mpd_unlock_conn(mi))
230 	{
231 		/*TODO free entity. for now this can never happen */
232 		return NULL;
233 	}
234     return data;
235 }
236 
mpd_playlist_get_current_song(MpdObj * mi)237 mpd_Song * mpd_playlist_get_current_song(MpdObj *mi)
238 {
239 	if(!mpd_check_connected(mi))
240 	{
241 		debug_printf(DEBUG_WARNING, "Not Connected\n");
242 		return NULL;
243 	}
244 
245 	if(mpd_status_check(mi) != MPD_OK)
246 	{
247 		debug_printf(DEBUG_ERROR, "Failed to check status\n");
248 		return NULL;
249 	}
250 
251 	if(mi->CurrentSong != NULL && mi->CurrentSong->id != mi->status->songid)
252 	{
253 		debug_printf(DEBUG_WARNING, "Current song not up2date, updating\n");
254 		mpd_freeSong(mi->CurrentSong);
255 		mi->CurrentSong = NULL;
256 	}
257 	/* only update song when playing/pasing */
258 	if(mi->CurrentSong == NULL &&
259 			(mpd_player_get_state(mi) != MPD_PLAYER_STOP && mpd_player_get_state(mi) != MPD_PLAYER_UNKNOWN))
260 	{
261 		/* TODO: this to use the geT_current_song_id function */
262 		mi->CurrentSong = mpd_playlist_get_song(mi, mpd_player_get_current_song_id(mi));
263 		if(mi->CurrentSong == NULL)
264 		{
265 			debug_printf(DEBUG_ERROR, "Failed to grab song\n");
266 			return NULL;
267 		}
268 	}
269 	return mi->CurrentSong;
270 }
271 
mpd_playlist_clear(MpdObj * mi)272 int mpd_playlist_clear(MpdObj *mi)
273 {
274 	if(!mpd_check_connected(mi))
275 	{
276 		debug_printf(DEBUG_WARNING,"not connected\n");
277 		return MPD_NOT_CONNECTED;
278 	}
279 	if(mpd_lock_conn(mi))
280 	{
281 		debug_printf(DEBUG_WARNING,"lock failed\n");
282 		return MPD_LOCK_FAILED;
283 	}
284 
285 	mpd_sendClearCommand(mi->connection);
286 	mpd_finishCommand(mi->connection);
287 	/* hack to make it update correctly when replacing 1 song */
288 	mi->CurrentState.songid = -1;
289 	/* unlock */
290 	mpd_unlock_conn(mi);
291 	mpd_status_update(mi);
292 	return FALSE;
293 }
294 
mpd_playlist_shuffle(MpdObj * mi)295 int mpd_playlist_shuffle(MpdObj *mi)
296 {
297 	if(!mpd_check_connected(mi))
298 	{
299 		debug_printf(DEBUG_WARNING,"not connected\n");
300 		return MPD_NOT_CONNECTED;
301 	}
302 	if(mpd_lock_conn(mi))
303 	{
304 		debug_printf(DEBUG_ERROR,"lock failed\n");
305 		return MPD_LOCK_FAILED;
306 	}
307 
308 	mpd_sendShuffleCommand(mi->connection);
309 	mpd_finishCommand(mi->connection);
310 
311 	/* unlock */
312 	mpd_unlock_conn(mi);
313 	return FALSE;
314 
315 }
316 
317 
mpd_playlist_move_id(MpdObj * mi,int old_id,int new_id)318 int mpd_playlist_move_id(MpdObj *mi, int old_id, int new_id)
319 {
320 	if(!mpd_check_connected(mi))
321 	{
322 		debug_printf(DEBUG_WARNING,"not connected\n");
323 		return MPD_NOT_CONNECTED;
324 	}
325 	if(mpd_lock_conn(mi))
326 	{
327 		debug_printf(DEBUG_ERROR,"lock failed\n");
328 		return MPD_LOCK_FAILED;
329 	}
330 
331 	mpd_sendMoveIdCommand(mi->connection,old_id, new_id);
332 	mpd_finishCommand(mi->connection);
333 
334 	/* unlock */
335 	mpd_unlock_conn(mi);
336 	return MPD_OK;
337 }
338 
mpd_playlist_move_pos(MpdObj * mi,int old_pos,int new_pos)339 int mpd_playlist_move_pos(MpdObj *mi, int old_pos, int new_pos)
340 {
341 	if(!mpd_check_connected(mi))
342 	{
343 		debug_printf(DEBUG_WARNING,"not connected\n");
344 		return MPD_NOT_CONNECTED;
345 	}
346 	if(mpd_lock_conn(mi))
347 	{
348 		debug_printf(DEBUG_ERROR,"lock failed\n");
349 		return MPD_LOCK_FAILED;
350 	}
351 
352 	mpd_sendMoveCommand(mi->connection,old_pos, new_pos);
353 	mpd_finishCommand(mi->connection);
354 
355 	/* unlock */
356 	mpd_unlock_conn(mi);
357 	return MPD_OK;
358 }
359 
mpd_playlist_get_changes(MpdObj * mi,int old_playlist_id)360 MpdData * mpd_playlist_get_changes(MpdObj *mi,int old_playlist_id)
361 {
362 	MpdData *data = NULL;
363 	mpd_InfoEntity *ent = NULL;
364 	if(!mpd_check_connected(mi))
365 	{
366 		debug_printf(DEBUG_WARNING,"not connected\n");
367 		return NULL;
368 	}
369 	if(mpd_lock_conn(mi))
370 	{
371 		debug_printf(DEBUG_WARNING,"lock failed\n");
372 		return NULL;
373 	}
374 
375 	if(old_playlist_id == -1)
376 	{
377 		debug_printf(DEBUG_INFO,"get fresh playlist\n");
378 		mpd_sendPlChangesCommand (mi->connection, 0);
379 /*		mpd_sendPlaylistIdCommand(mi->connection, -1); */
380 	}
381 	else
382 	{
383 		mpd_sendPlChangesCommand (mi->connection, old_playlist_id);
384 	}
385 
386 	while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
387 	{
388 		if(ent->type == MPD_INFO_ENTITY_TYPE_SONG)
389 		{
390 			data = mpd_new_data_struct_append(data);
391 			data->type = MPD_DATA_TYPE_SONG;
392 			data->song = ent->info.song;
393 			ent->info.song = NULL;
394 		}
395 		mpd_freeInfoEntity(ent);
396 	}
397 	mpd_finishCommand(mi->connection);
398 
399 	/* unlock */
400 	if(mpd_unlock_conn(mi))
401 	{
402 		debug_printf(DEBUG_WARNING,"mpd_playlist_get_changes: unlock failed.\n");
403 		mpd_data_free(data);
404 		return NULL;
405 	}
406 	if(data == NULL)
407 	{
408 		return NULL;
409 	}
410 	return mpd_data_get_first(data);
411 }
412 
413 
414 
mpd_playlist_get_changes_posid(MpdObj * mi,int old_playlist_id)415 MpdData * mpd_playlist_get_changes_posid(MpdObj *mi,int old_playlist_id)
416 {
417 	MpdData *data = NULL;
418 	mpd_InfoEntity *ent = NULL;
419 	debug_printf(DEBUG_INFO, "Fetching using new plchangesposid command");
420 	if(!mpd_check_connected(mi))
421 	{
422 		debug_printf(DEBUG_WARNING,"not connected\n");
423 		return NULL;
424 	}
425 	if(mpd_lock_conn(mi))
426 	{
427 		debug_printf(DEBUG_WARNING,"lock failed\n");
428 		return NULL;
429 	}
430 
431 	if(old_playlist_id == -1)
432 	{
433 		debug_printf(DEBUG_INFO,"get fresh playlist\n");
434 		mpd_sendPlChangesPosIdCommand (mi->connection, 0);
435 /*		mpd_sendPlaylistIdCommand(mi->connection, -1); */
436 	}
437 	else
438 	{
439 		mpd_sendPlChangesPosIdCommand (mi->connection, old_playlist_id);
440 	}
441 
442 	while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
443 	{
444 		if(ent->type == MPD_INFO_ENTITY_TYPE_SONG)
445 		{
446 			data = mpd_new_data_struct_append(data);
447 			data->type = MPD_DATA_TYPE_SONG;
448 			data->song = ent->info.song;
449 			ent->info.song = NULL;
450 		}
451 		mpd_freeInfoEntity(ent);
452 	}
453 	mpd_finishCommand(mi->connection);
454 
455 	/* unlock */
456 	if(mpd_unlock_conn(mi))
457 	{
458 		debug_printf(DEBUG_WARNING,"mpd_playlist_get_changes: unlock failed.\n");
459 		mpd_data_free(data);
460 		return NULL;
461 	}
462 	if(data == NULL)
463 	{
464 		return NULL;
465 	}
466 	return mpd_data_get_first(data);
467 }
468 
mpd_playlist_queue_add(MpdObj * mi,const char * path)469 int mpd_playlist_queue_add(MpdObj *mi,const char *path)
470 {
471 	if(!mpd_check_connected(mi))
472 	{
473 		debug_printf(DEBUG_WARNING,"not connected\n");
474 		return MPD_NOT_CONNECTED;
475 	}
476 	if(path == NULL)
477 	{
478 		debug_printf(DEBUG_ERROR, "path != NULL Failed");
479 		return MPD_ARGS_ERROR;
480 	}
481 
482 	if(mi->queue == NULL)
483 	{
484 		mi->queue = mpd_new_queue_struct();
485 		mi->queue->first = mi->queue;
486 		mi->queue->next = NULL;
487 		mi->queue->prev = NULL;
488 	}
489 	else
490 	{
491 		mi->queue->next = mpd_new_queue_struct();
492 		mi->queue->next->first = mi->queue->first;
493 		mi->queue->next->prev = mi->queue;
494 		mi->queue = mi->queue->next;
495 		mi->queue->next = NULL;
496 	}
497 	mi->queue->type = MPD_QUEUE_ADD;
498 	mi->queue->path = strdup(path);
499 	return MPD_OK;
500 }
501 
mpd_playlist_queue_load(MpdObj * mi,const char * path)502 int mpd_playlist_queue_load(MpdObj *mi,const char *path)
503 {
504 	if(!mpd_check_connected(mi))
505 	{
506 		debug_printf(DEBUG_WARNING,"not connected\n");
507 		return MPD_NOT_CONNECTED;
508 	}
509 	if(path == NULL)
510 	{
511 		debug_printf(DEBUG_ERROR, "path != NULL Failed");
512 		return MPD_ARGS_ERROR;
513 	}
514 
515 	if(mi->queue == NULL)
516 	{
517 		mi->queue = mpd_new_queue_struct();
518 		mi->queue->first = mi->queue;
519 		mi->queue->next = NULL;
520 		mi->queue->prev = NULL;
521 	}
522 	else
523 	{
524 		mi->queue->next = mpd_new_queue_struct();
525 		mi->queue->next->first = mi->queue->first;
526 		mi->queue->next->prev = mi->queue;
527 		mi->queue = mi->queue->next;
528 		mi->queue->next = NULL;
529 	}
530 	mi->queue->type = MPD_QUEUE_LOAD;
531 	mi->queue->path = strdup(path);
532 	return MPD_OK;
533 }
534 
535 
mpd_playlist_queue_commit(MpdObj * mi)536 int mpd_playlist_queue_commit(MpdObj *mi)
537 {
538 	if(!mpd_check_connected(mi))
539 	{
540 		debug_printf(DEBUG_WARNING,"not connected\n");
541 		return MPD_NOT_CONNECTED;
542 	}
543 	if(mi->queue == NULL)
544 	{
545 		debug_printf(DEBUG_WARNING,"mi->queue is empty");
546 		return MPD_PLAYLIST_QUEUE_EMPTY;
547 	}
548 	if(mpd_lock_conn(mi))
549 	{
550 		debug_printf(DEBUG_WARNING,"lock failed\n");
551 		return  MPD_LOCK_FAILED;
552 	}
553 	mpd_sendCommandListBegin(mi->connection);
554 	/* get first item */
555 	mi->queue = mi->queue->first;
556 	while(mi->queue != NULL)
557 	{
558 		if(mi->queue->type == MPD_QUEUE_ADD)
559 		{
560 			if(mi->queue->path != NULL)
561 			{
562 				mpd_sendAddCommand(mi->connection, mi->queue->path);
563 			}
564 		}
565 		else if(mi->queue->type == MPD_QUEUE_LOAD)
566 		{
567 			if(mi->queue->path != NULL)
568 			{
569 				mpd_sendLoadCommand(mi->connection, mi->queue->path);
570 			}
571 		}
572 		else if (mi->queue->type == MPD_QUEUE_DELETE_ID)
573 		{
574 			if(mi->queue->id >= 0)
575 			{
576 				mpd_sendDeleteIdCommand(mi->connection, mi->queue->id);
577 			}
578 		}
579 		else if (mi->queue->type == MPD_QUEUE_DELETE_POS)
580 		{
581 			if(mi->queue->id >= 0)
582 			{
583 				mpd_sendDeleteCommand(mi->connection, mi->queue->id);
584 			}
585 		}
586 
587 		mpd_queue_get_next(mi);
588 	}
589 	mpd_sendCommandListEnd(mi->connection);
590 	mpd_finishCommand(mi->connection);
591 
592 
593 
594 	mpd_unlock_conn(mi);
595 	mpd_status_update(mi);
596 	return MPD_OK;
597 }
mpd_playlist_queue_delete_id(MpdObj * mi,int id)598 int mpd_playlist_queue_delete_id(MpdObj *mi,int id)
599 {
600 	if(!mpd_check_connected(mi))
601 	{
602 		debug_printf(DEBUG_WARNING,"not connected\n");
603 		return MPD_NOT_CONNECTED;
604 	}
605 
606 	if(mi->queue == NULL)
607 	{
608 		mi->queue = mpd_new_queue_struct();
609 		mi->queue->first = mi->queue;
610 		mi->queue->next = NULL;
611 		mi->queue->prev = NULL;
612 	}
613 	else
614 	{
615 		mi->queue->next = mpd_new_queue_struct();
616 		mi->queue->next->first = mi->queue->first;
617 		mi->queue->next->prev = mi->queue;
618 		mi->queue = mi->queue->next;
619 		mi->queue->next = NULL;
620 	}
621 	mi->queue->type = MPD_QUEUE_DELETE_ID;
622 	mi->queue->id = id;
623 	mi->queue->path = NULL;
624 	return MPD_OK;
625 }
626 
mpd_playlist_queue_delete_pos(MpdObj * mi,int songpos)627 int mpd_playlist_queue_delete_pos(MpdObj *mi,int songpos)
628 {
629 	if(!mpd_check_connected(mi))
630 	{
631 		debug_printf(DEBUG_WARNING,"mpd_playlist_add: not connected\n");
632 		return MPD_NOT_CONNECTED;
633 	}
634 
635 	if(mi->queue == NULL)
636 	{
637 		mi->queue = mpd_new_queue_struct();
638 		mi->queue->first = mi->queue;
639 		mi->queue->next = NULL;
640 		mi->queue->prev = NULL;
641 	}
642 	else
643 	{
644 		mi->queue->next = mpd_new_queue_struct();
645 		mi->queue->next->first = mi->queue->first;
646 		mi->queue->next->prev = mi->queue;
647 		mi->queue = mi->queue->next;
648 		mi->queue->next = NULL;
649 	}
650 	mi->queue->type = MPD_QUEUE_DELETE_POS;
651 	mi->queue->id = songpos;
652 	mi->queue->path = NULL;
653 	return MPD_OK;
654 }
655 
mpd_playlist_add_get_id(MpdObj * mi,const char * path)656 int mpd_playlist_add_get_id(MpdObj *mi,const char *path)
657 {
658 	int songid = -1;
659 	if(mi == NULL || path == NULL)
660 	{
661 		debug_printf(DEBUG_ERROR, "mi == NULL || path == NULL failed");
662 		return MPD_ARGS_ERROR;
663 	}
664 	if(!mpd_check_connected(mi))
665 	{
666 		debug_printf(DEBUG_WARNING,"mpd_playlist_add: not connected\n");
667 		return MPD_NOT_CONNECTED;
668 	}
669 	if(mpd_lock_conn(mi))
670 	{
671 		debug_printf(DEBUG_WARNING,"lock failed\n");
672 		return MPD_LOCK_FAILED;
673 	}
674 	songid = mpd_sendAddIdCommand(mi->connection, path);
675 	mpd_finishCommand(mi->connection);
676 
677 	mpd_unlock_conn(mi);
678 	return songid;
679 }
680 
mpd_playlist_search_start(MpdObj * mi,int exact)681 void mpd_playlist_search_start(MpdObj *mi, int exact)
682 {
683 	/*
684 	 * Check argument
685 	 */
686 	if(mi == NULL || exact > 1 || exact < 0)
687 	{
688 		debug_printf(DEBUG_ERROR, "Argument error");
689 		return ;
690 	}
691 	if(!mpd_check_connected(mi))
692 	{
693 		debug_printf(DEBUG_ERROR, "Not Connected\n");
694 		return ;
695 	}
696 	if(!mpd_server_check_version(mi, 0,12,1))
697 	{
698 		debug_printf(DEBUG_ERROR, "Advanced search requires mpd 0.12.2 or higher");
699 		return ;
700 	}
701 	/* lock, so we can work on mi->connection */
702 	if(mpd_lock_conn(mi) != MPD_OK)
703 	{
704 		debug_printf(DEBUG_ERROR, "Failed to lock connection");
705 		return ;
706 	}
707 	mpd_startPlaylistSearch(mi->connection, exact);
708 	/* Set search type */
709 	mi->search_type = (exact)? MPD_SEARCH_TYPE_PLAYLIST_FIND:MPD_SEARCH_TYPE_PLAYLIST_SEARCH;
710 	/* unlock, let the error handler handle any possible error.
711 	 */
712 	mpd_unlock_conn(mi);
713 	return;
714 }
715 
mpd_playlist_search_add_constraint(MpdObj * mi,mpd_TagItems field,const char * value)716 void mpd_playlist_search_add_constraint(MpdObj *mi, mpd_TagItems field,const char *value)
717 {
718 	mpd_database_search_add_constraint(mi, field, value);
719 }
mpd_playlist_search_commit(MpdObj * mi)720 MpdData * mpd_playlist_search_commit(MpdObj *mi)
721 {
722 	mpd_InfoEntity *ent = NULL;
723 	MpdData *data = NULL;
724 	if(!mpd_check_connected(mi))
725 	{
726 		debug_printf(DEBUG_WARNING,"not connected\n");
727 		return NULL;
728 	}
729 	if(mi->search_type < MPD_SEARCH_TYPE_PLAYLIST_FIND )
730 	{
731 		debug_printf(DEBUG_ERROR, "no or wrong search in progress to commit");
732 		return NULL;
733 	}
734 	if(mpd_lock_conn(mi))
735 	{
736 		debug_printf(DEBUG_ERROR,"lock failed\n");
737 		return NULL;
738 	}
739 	mpd_commitSearch(mi->connection);
740 	while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
741 	{
742 		if(ent->type == MPD_INFO_ENTITY_TYPE_SONG)
743 		{
744 			data = mpd_new_data_struct_append(data);
745 			data->type = MPD_DATA_TYPE_SONG;
746 			data->song = ent->info.song;
747 			ent->info.song = NULL;
748 		}
749 		mpd_freeInfoEntity(ent);
750 	}
751 	mpd_finishCommand(mi->connection);
752 	/*
753 	 * reset search type
754 	 */
755 	mi->search_type = MPD_SEARCH_TYPE_NONE;
756 	mi->search_field = MPD_TAG_ITEM_ARTIST;
757 	/* unlock */
758 	if(mpd_unlock_conn(mi))
759 	{
760 		debug_printf(DEBUG_ERROR, "Failed to unlock connection");
761 		if(data)mpd_data_free(data);
762 		return NULL;
763 	}
764 	if(data == NULL)
765 	{
766 		return NULL;
767 	}
768 	return mpd_data_get_first(data);
769 }
770 
771 
mpd_playlist_load(MpdObj * mi,const char * path)772 int mpd_playlist_load(MpdObj *mi, const char *path)
773 {
774     int retv = MPD_OK;
775 	if(!mpd_check_connected(mi))
776 	{
777 		debug_printf(DEBUG_WARNING,"mpd_playlist_load: not connected\n");
778 		return MPD_NOT_CONNECTED;
779 	}
780 	if(mpd_lock_conn(mi))
781 	{
782 		debug_printf(DEBUG_ERROR,"lock failed\n");
783 		return NULL;
784 	}
785     mpd_sendLoadCommand(mi->connection,path);
786 	mpd_finishCommand(mi->connection);
787     if(mi->connection->errorCode == MPD_ACK_ERROR_NO_EXIST)
788     {
789         debug_printf(DEBUG_WARNING, "mpd_playlist_load: failed to load playlist\n");
790 		mpd_clearError(mi->connection);
791         retv = MPD_PLAYLIST_LOAD_FAILED;
792     }
793 
794 	if(mpd_unlock_conn(mi))
795 	{
796 		debug_printf(DEBUG_ERROR, "Failed to unlock connection");
797 		return MPD_LOCK_FAILED;
798 	}
799     return retv;
800 }
801