2 *Copyright (C) 2004-2007 Qball Cow <Qball@qballcow.nl>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public
15 * License along with this program; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
27 #include "debug_printf.h"
29 #include "libmpd-internal.h"
32 int mpd_playlist_get_playlist_length(MpdObj
*mi
)
34 if(!mpd_check_connected(mi
))
36 debug_printf(DEBUG_WARNING
,"not connected\n");
37 return MPD_NOT_CONNECTED
;
39 if(mpd_status_check(mi
) != MPD_OK
)
41 debug_printf(DEBUG_ERROR
,"Failed grabbing status\n");
42 return MPD_STATUS_FAILED
;
44 return mi
->status
->playlistLength
;
47 long long mpd_playlist_get_old_playlist_id(MpdObj
*mi
)
49 return mi
->OldState
.playlistid
;
52 long long mpd_playlist_get_playlist_id(MpdObj
*mi
)
54 if(!mpd_check_connected(mi
))
56 debug_printf(DEBUG_WARNING
,"not connected\n");
57 return MPD_NOT_CONNECTED
;
59 if(mpd_status_check(mi
) != MPD_OK
)
61 debug_printf(DEBUG_WARNING
,"Failed grabbing status\n");
62 return MPD_STATUS_FAILED
;
64 return mi
->status
->playlist
;
66 int mpd_playlist_add(MpdObj
*mi
, char *path
)
68 int retv
= mpd_playlist_queue_add(mi
, path
);
69 if(retv
!= MPD_OK
) return retv
;
70 return mpd_playlist_queue_commit(mi
);
73 int mpd_playlist_delete_id(MpdObj
*mi
, int songid
)
75 int retv
= mpd_playlist_queue_delete_id(mi
, songid
);
76 if(retv
!= MPD_OK
) return retv
;
77 return mpd_playlist_queue_commit(mi
);
80 int mpd_playlist_delete_pos(MpdObj
*mi
, int songpos
)
82 int retv
= mpd_playlist_queue_delete_pos(mi
, songpos
);
83 if(retv
!= MPD_OK
) return retv
;
84 return mpd_playlist_queue_commit(mi
);
86 /*******************************************************************************
89 mpd_Song
* mpd_playlist_get_song(MpdObj
*mi
, int songid
)
91 mpd_Song
*song
= NULL
;
92 mpd_InfoEntity
*ent
= NULL
;
94 debug_printf(DEBUG_ERROR
, "songid < 0 Failed");
97 if(!mpd_check_connected(mi
))
99 debug_printf(DEBUG_ERROR
, "Not Connected\n");
103 if(mpd_lock_conn(mi
))
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
);
112 if(mpd_unlock_conn(mi
))
114 if(ent
) mpd_freeInfoEntity(ent
);
120 debug_printf(DEBUG_ERROR
, "Failed to grab song from mpd\n");
124 if(ent
->type
!= MPD_INFO_ENTITY_TYPE_SONG
)
126 mpd_freeInfoEntity(ent
);
127 debug_printf(DEBUG_ERROR
, "Failed to grab correct song type from mpd\n");
130 song
= ent
->info
.song
;
131 ent
->info
.song
= NULL
;
133 mpd_freeInfoEntity(ent
);
138 mpd_Song
* mpd_playlist_get_song_from_pos(MpdObj
*mi
, int songpos
)
140 mpd_Song
*song
= NULL
;
141 mpd_InfoEntity
*ent
= NULL
;
143 debug_printf(DEBUG_ERROR
, "songpos < 0 Failed");
146 if(!mpd_check_connected(mi
))
148 debug_printf(DEBUG_ERROR
, "Not Connected\n");
152 if(mpd_lock_conn(mi
))
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
);
161 if(mpd_unlock_conn(mi
))
163 /*TODO free entity. for now this can never happen */
169 debug_printf(DEBUG_ERROR
, "Failed to grab song from mpd\n");
173 if(ent
->type
!= MPD_INFO_ENTITY_TYPE_SONG
)
175 mpd_freeInfoEntity(ent
);
176 debug_printf(DEBUG_ERROR
, "Failed to grab corect song type from mpd\n");
179 song
= ent
->info
.song
;
180 ent
->info
.song
= NULL
;
182 mpd_freeInfoEntity(ent
);
187 mpd_Song
* mpd_playlist_get_current_song(MpdObj
*mi
)
189 if(!mpd_check_connected(mi
))
191 debug_printf(DEBUG_ERROR
, "Not Connected\n");
195 if(mpd_status_check(mi
) != MPD_OK
)
197 debug_printf(DEBUG_ERROR
, "Failed to check status\n");
201 if(mi
->CurrentSong
!= NULL
&& mi
->CurrentSong
->id
!= mi
->status
->songid
)
203 debug_printf(DEBUG_WARNING
, "Current song not up2date, updating\n");
204 mpd_freeSong(mi
->CurrentSong
);
205 mi
->CurrentSong
= NULL
;
207 /* only update song when playing/pasing */
208 if(mi
->CurrentSong
== NULL
&&
209 (mpd_player_get_state(mi
) != MPD_PLAYER_STOP
&& mpd_player_get_state(mi
) != MPD_PLAYER_UNKNOWN
))
211 /* TODO: this to use the geT_current_song_id function */
212 mi
->CurrentSong
= mpd_playlist_get_song(mi
, mpd_player_get_current_song_id(mi
));
213 if(mi
->CurrentSong
== NULL
)
215 debug_printf(DEBUG_ERROR
, "Failed to grab song\n");
219 return mi
->CurrentSong
;
222 int mpd_playlist_clear(MpdObj
*mi
)
224 if(!mpd_check_connected(mi
))
226 debug_printf(DEBUG_WARNING
,"not connected\n");
227 return MPD_NOT_CONNECTED
;
229 if(mpd_lock_conn(mi
))
231 debug_printf(DEBUG_WARNING
,"lock failed\n");
232 return MPD_LOCK_FAILED
;
235 mpd_sendClearCommand(mi
->connection
);
236 mpd_finishCommand(mi
->connection
);
237 /* hack to make it update correctly when replacing 1 song */
238 mi
->CurrentState
.songid
= -1;
241 mpd_status_update(mi
);
245 int mpd_playlist_shuffle(MpdObj
*mi
)
247 if(!mpd_check_connected(mi
))
249 debug_printf(DEBUG_WARNING
,"not connected\n");
250 return MPD_NOT_CONNECTED
;
252 if(mpd_lock_conn(mi
))
254 debug_printf(DEBUG_ERROR
,"lock failed\n");
255 return MPD_LOCK_FAILED
;
258 mpd_sendShuffleCommand(mi
->connection
);
259 mpd_finishCommand(mi
->connection
);
268 int mpd_playlist_move_id(MpdObj
*mi
, int old_id
, int new_id
)
270 if(!mpd_check_connected(mi
))
272 debug_printf(DEBUG_WARNING
,"not connected\n");
273 return MPD_NOT_CONNECTED
;
275 if(mpd_lock_conn(mi
))
277 debug_printf(DEBUG_ERROR
,"lock failed\n");
278 return MPD_LOCK_FAILED
;
281 mpd_sendMoveIdCommand(mi
->connection
,old_id
, new_id
);
282 mpd_finishCommand(mi
->connection
);
289 int mpd_playlist_move_pos(MpdObj
*mi
, int old_pos
, int new_pos
)
291 if(!mpd_check_connected(mi
))
293 debug_printf(DEBUG_WARNING
,"not connected\n");
294 return MPD_NOT_CONNECTED
;
296 if(mpd_lock_conn(mi
))
298 debug_printf(DEBUG_ERROR
,"lock failed\n");
299 return MPD_LOCK_FAILED
;
302 mpd_sendMoveCommand(mi
->connection
,old_pos
, new_pos
);
303 mpd_finishCommand(mi
->connection
);
310 MpdData
* mpd_playlist_get_changes(MpdObj
*mi
,int old_playlist_id
)
312 MpdData
*data
= NULL
;
313 mpd_InfoEntity
*ent
= NULL
;
314 if(!mpd_check_connected(mi
))
316 debug_printf(DEBUG_WARNING
,"not connected\n");
319 if(mpd_lock_conn(mi
))
321 debug_printf(DEBUG_WARNING
,"lock failed\n");
325 if(old_playlist_id
== -1)
327 debug_printf(DEBUG_INFO
,"get fresh playlist\n");
328 mpd_sendPlChangesCommand (mi
->connection
, 0);
329 /* mpd_sendPlaylistIdCommand(mi->connection, -1); */
333 mpd_sendPlChangesCommand (mi
->connection
, old_playlist_id
);
336 while (( ent
= mpd_getNextInfoEntity(mi
->connection
)) != NULL
)
338 if(ent
->type
== MPD_INFO_ENTITY_TYPE_SONG
)
340 data
= mpd_new_data_struct_append(data
);
341 data
->type
= MPD_DATA_TYPE_SONG
;
342 data
->song
= ent
->info
.song
;
343 ent
->info
.song
= NULL
;
345 mpd_freeInfoEntity(ent
);
347 mpd_finishCommand(mi
->connection
);
350 if(mpd_unlock_conn(mi
))
352 debug_printf(DEBUG_WARNING
,"mpd_playlist_get_changes: unlock failed.\n");
360 return mpd_data_get_first(data
);
365 MpdData
* mpd_playlist_get_changes_posid(MpdObj
*mi
,int old_playlist_id
)
367 MpdData
*data
= NULL
;
368 mpd_InfoEntity
*ent
= NULL
;
369 debug_printf(DEBUG_INFO
, "Fetching using new plchangesposid command");
370 if(!mpd_check_connected(mi
))
372 debug_printf(DEBUG_WARNING
,"not connected\n");
375 if(mpd_lock_conn(mi
))
377 debug_printf(DEBUG_WARNING
,"lock failed\n");
381 if(old_playlist_id
== -1)
383 debug_printf(DEBUG_INFO
,"get fresh playlist\n");
384 mpd_sendPlChangesPosIdCommand (mi
->connection
, 0);
385 /* mpd_sendPlaylistIdCommand(mi->connection, -1); */
389 mpd_sendPlChangesPosIdCommand (mi
->connection
, old_playlist_id
);
392 while (( ent
= mpd_getNextInfoEntity(mi
->connection
)) != NULL
)
394 if(ent
->type
== MPD_INFO_ENTITY_TYPE_SONG
)
396 data
= mpd_new_data_struct_append(data
);
397 data
->type
= MPD_DATA_TYPE_SONG
;
398 data
->song
= ent
->info
.song
;
399 ent
->info
.song
= NULL
;
401 mpd_freeInfoEntity(ent
);
403 mpd_finishCommand(mi
->connection
);
406 if(mpd_unlock_conn(mi
))
408 debug_printf(DEBUG_WARNING
,"mpd_playlist_get_changes: unlock failed.\n");
416 return mpd_data_get_first(data
);
419 int mpd_playlist_queue_add(MpdObj
*mi
,char *path
)
421 if(!mpd_check_connected(mi
))
423 debug_printf(DEBUG_WARNING
,"not connected\n");
424 return MPD_NOT_CONNECTED
;
428 debug_printf(DEBUG_ERROR
, "path != NULL Failed");
429 return MPD_ARGS_ERROR
;
432 if(mi
->queue
== NULL
)
434 mi
->queue
= mpd_new_queue_struct();
435 mi
->queue
->first
= mi
->queue
;
436 mi
->queue
->next
= NULL
;
437 mi
->queue
->prev
= NULL
;
441 mi
->queue
->next
= mpd_new_queue_struct();
442 mi
->queue
->next
->first
= mi
->queue
->first
;
443 mi
->queue
->next
->prev
= mi
->queue
;
444 mi
->queue
= mi
->queue
->next
;
445 mi
->queue
->next
= NULL
;
447 mi
->queue
->type
= MPD_QUEUE_ADD
;
448 mi
->queue
->path
= strdup(path
);
452 int mpd_playlist_queue_load(MpdObj
*mi
,char *path
)
454 if(!mpd_check_connected(mi
))
456 debug_printf(DEBUG_WARNING
,"not connected\n");
457 return MPD_NOT_CONNECTED
;
461 debug_printf(DEBUG_ERROR
, "path != NULL Failed");
462 return MPD_ARGS_ERROR
;
465 if(mi
->queue
== NULL
)
467 mi
->queue
= mpd_new_queue_struct();
468 mi
->queue
->first
= mi
->queue
;
469 mi
->queue
->next
= NULL
;
470 mi
->queue
->prev
= NULL
;
474 mi
->queue
->next
= mpd_new_queue_struct();
475 mi
->queue
->next
->first
= mi
->queue
->first
;
476 mi
->queue
->next
->prev
= mi
->queue
;
477 mi
->queue
= mi
->queue
->next
;
478 mi
->queue
->next
= NULL
;
480 mi
->queue
->type
= MPD_QUEUE_LOAD
;
481 mi
->queue
->path
= strdup(path
);
486 int mpd_playlist_queue_commit(MpdObj
*mi
)
488 if(mi
->queue
== NULL
)
490 debug_printf(DEBUG_WARNING
,"mi->queue is empty");
491 return MPD_PLAYLIST_QUEUE_EMPTY
;
493 if(!mpd_check_connected(mi
))
495 debug_printf(DEBUG_WARNING
,"not connected\n");
496 return MPD_NOT_CONNECTED
;
498 if(mpd_lock_conn(mi
))
500 debug_printf(DEBUG_WARNING
,"lock failed\n");
501 return MPD_LOCK_FAILED
;
503 mpd_sendCommandListBegin(mi
->connection
);
505 mi
->queue
= mi
->queue
->first
;
506 while(mi
->queue
!= NULL
)
508 if(mi
->queue
->type
== MPD_QUEUE_ADD
)
510 if(mi
->queue
->path
!= NULL
)
512 mpd_sendAddCommand(mi
->connection
, mi
->queue
->path
);
515 else if(mi
->queue
->type
== MPD_QUEUE_LOAD
)
517 if(mi
->queue
->path
!= NULL
)
519 mpd_sendLoadCommand(mi
->connection
, mi
->queue
->path
);
522 else if (mi
->queue
->type
== MPD_QUEUE_DELETE_ID
)
524 if(mi
->queue
->id
>= 0)
526 mpd_sendDeleteIdCommand(mi
->connection
, mi
->queue
->id
);
529 else if (mi
->queue
->type
== MPD_QUEUE_DELETE_POS
)
531 if(mi
->queue
->id
>= 0)
533 mpd_sendDeleteCommand(mi
->connection
, mi
->queue
->id
);
537 mpd_queue_get_next(mi
);
539 mpd_sendCommandListEnd(mi
->connection
);
540 mpd_finishCommand(mi
->connection
);
542 mpd_status_update(mi
);
545 int mpd_playlist_queue_delete_id(MpdObj
*mi
,int id
)
547 if(!mpd_check_connected(mi
))
549 debug_printf(DEBUG_WARNING
,"not connected\n");
550 return MPD_NOT_CONNECTED
;
553 if(mi
->queue
== NULL
)
555 mi
->queue
= mpd_new_queue_struct();
556 mi
->queue
->first
= mi
->queue
;
557 mi
->queue
->next
= NULL
;
558 mi
->queue
->prev
= NULL
;
562 mi
->queue
->next
= mpd_new_queue_struct();
563 mi
->queue
->next
->first
= mi
->queue
->first
;
564 mi
->queue
->next
->prev
= mi
->queue
;
565 mi
->queue
= mi
->queue
->next
;
566 mi
->queue
->next
= NULL
;
568 mi
->queue
->type
= MPD_QUEUE_DELETE_ID
;
570 mi
->queue
->path
= NULL
;
574 int mpd_playlist_queue_delete_pos(MpdObj
*mi
,int songpos
)
576 if(!mpd_check_connected(mi
))
578 debug_printf(DEBUG_WARNING
,"mpd_playlist_add: not connected\n");
579 return MPD_NOT_CONNECTED
;
582 if(mi
->queue
== NULL
)
584 mi
->queue
= mpd_new_queue_struct();
585 mi
->queue
->first
= mi
->queue
;
586 mi
->queue
->next
= NULL
;
587 mi
->queue
->prev
= NULL
;
591 mi
->queue
->next
= mpd_new_queue_struct();
592 mi
->queue
->next
->first
= mi
->queue
->first
;
593 mi
->queue
->next
->prev
= mi
->queue
;
594 mi
->queue
= mi
->queue
->next
;
595 mi
->queue
->next
= NULL
;
597 mi
->queue
->type
= MPD_QUEUE_DELETE_POS
;
598 mi
->queue
->id
= songpos
;
599 mi
->queue
->path
= NULL
;
603 int mpd_playlist_add_get_id(MpdObj
*mi
, char *path
)
606 if(mi
== NULL
|| path
== NULL
)
608 debug_printf(DEBUG_ERROR
, "mi == NULL || path == NULL failed");
609 return MPD_ARGS_ERROR
;
611 if(!mpd_check_connected(mi
))
613 debug_printf(DEBUG_WARNING
,"mpd_playlist_add: not connected\n");
614 return MPD_NOT_CONNECTED
;
616 if(mpd_lock_conn(mi
))
618 debug_printf(DEBUG_WARNING
,"lock failed\n");
619 return MPD_LOCK_FAILED
;
621 songid
= mpd_sendAddIdCommand(mi
->connection
, path
);
622 mpd_finishCommand(mi
->connection
);
628 void mpd_playlist_search_start(MpdObj
*mi
, int exact
)
633 if(mi
== NULL
|| exact
> 1 || exact
< 0)
635 debug_printf(DEBUG_ERROR
, "Argument error");
638 if(!mpd_check_connected(mi
))
640 debug_printf(DEBUG_ERROR
, "Not Connected\n");
643 if(!mpd_server_check_version(mi
, 0,12,1))
645 debug_printf(DEBUG_ERROR
, "Advanced search requires mpd 0.12.2 or higher");
648 /* lock, so we can work on mi->connection */
649 if(mpd_lock_conn(mi
) != MPD_OK
)
651 debug_printf(DEBUG_ERROR
, "Failed to lock connection");
654 mpd_startPlaylistSearch(mi
->connection
, exact
);
655 /* Set search type */
656 mi
->search_type
= (exact
)? MPD_SEARCH_TYPE_PLAYLIST_FIND
:MPD_SEARCH_TYPE_PLAYLIST_SEARCH
;
657 /* unlock, let the error handler handle any possible error.
663 void mpd_playlist_search_add_constraint(MpdObj
*mi
, mpd_TagItems field
,const char *value
)
665 mpd_database_search_add_constraint(mi
, field
, value
);
667 MpdData
* mpd_playlist_search_commit(MpdObj
*mi
)
669 mpd_InfoEntity
*ent
= NULL
;
670 MpdData
*data
= NULL
;
671 if(!mpd_check_connected(mi
))
673 debug_printf(DEBUG_WARNING
,"not connected\n");
676 if(mi
->search_type
< MPD_SEARCH_TYPE_PLAYLIST_FIND
)
678 debug_printf(DEBUG_ERROR
, "no or wrong search in progress to commit");
681 if(mpd_lock_conn(mi
))
683 debug_printf(DEBUG_ERROR
,"lock failed\n");
686 mpd_commitSearch(mi
->connection
);
687 while (( ent
= mpd_getNextInfoEntity(mi
->connection
)) != NULL
)
689 if(ent
->type
== MPD_INFO_ENTITY_TYPE_SONG
)
691 data
= mpd_new_data_struct_append(data
);
692 data
->type
= MPD_DATA_TYPE_SONG
;
693 data
->song
= ent
->info
.song
;
694 ent
->info
.song
= NULL
;
696 mpd_freeInfoEntity(ent
);
698 mpd_finishCommand(mi
->connection
);
702 mi
->search_type
= MPD_SEARCH_TYPE_NONE
;
703 mi
->search_field
= MPD_TAG_ITEM_ARTIST
;
705 if(mpd_unlock_conn(mi
))
707 debug_printf(DEBUG_ERROR
, "Failed to unlock connection");
708 if(data
)mpd_data_free(data
);
715 return mpd_data_get_first(data
);