Implement consume, single mode.
[libmpd.git] / src / libmpd-database.c
blobabfcd3882d673582954f24a01a8aace1a51dcc2d
1 /* libmpd (high level libmpdclient library)
2 * Copyright (C) 2004-2009 Qball Cow <qball@sarine.nl>
3 * Project homepage: http://gmpcwiki.sarine.nl/
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.
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.
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.
20 #include <stdio.h>
21 #include <stdlib.h>
22 #define __USE_GNU
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"
31 int mpd_database_update_dir(MpdObj *mi,const char *path)
33 if(path == NULL || !strlen(path))
35 debug_printf(DEBUG_ERROR, "path != NULL and strlen(path) > 0 failed");
36 return MPD_ARGS_ERROR;
38 if(!mpd_check_connected(mi))
40 debug_printf(DEBUG_WARNING,"not connected\n");
41 return MPD_NOT_CONNECTED;
43 if(mpd_lock_conn(mi))
45 debug_printf(DEBUG_ERROR,"lock failed\n");
46 return MPD_LOCK_FAILED;
49 mpd_sendUpdateCommand(mi->connection,path);
50 mpd_finishCommand(mi->connection);
51 /* I have no idea why do this ?? it even makes gmpc very very unhappy.
52 * Because it doesnt trigger an signal anymore when updating starts
53 * mi->CurrentState.updatingDb = mpd_getUpdateId(mi->connection);
56 /* unlock */
57 mpd_unlock_conn(mi);
58 /* What I think you should do is to force a direct status updated
60 mpd_status_update(mi);
61 return MPD_OK;
64 MpdData * mpd_database_get_artists(MpdObj *mi)
66 char *string = NULL;
67 MpdData *data = NULL;
68 if(!mpd_check_connected(mi))
70 debug_printf(DEBUG_WARNING,"not connected\n");
71 return NULL;
73 if(mpd_lock_conn(mi))
75 debug_printf(DEBUG_ERROR,"lock failed\n");
76 return NULL;
79 mpd_sendListCommand(mi->connection,MPD_TABLE_ARTIST,NULL);
80 while (( string = mpd_getNextArtist(mi->connection)) != NULL)
82 data = mpd_new_data_struct_append(data);
83 data->type = MPD_DATA_TYPE_TAG;
84 data->tag_type = MPD_TAG_ITEM_ARTIST;
85 data->tag = string;
87 mpd_finishCommand(mi->connection);
89 /* unlock */
90 mpd_unlock_conn(mi);
91 if(data == NULL)
93 return NULL;
95 /* data = mpd_misc_sort_tag_list(data);*/
96 return mpd_data_get_first(data);
99 MpdData * mpd_database_get_albums(MpdObj *mi,const char *artist)
101 char *string = NULL;
102 MpdData *data = NULL;
103 if(!mpd_check_connected(mi))
105 debug_printf(DEBUG_WARNING,"not connected\n");
106 return NULL;
108 if(mpd_lock_conn(mi))
110 debug_printf(DEBUG_ERROR,"lock failed\n");
111 return NULL;
114 mpd_sendListCommand(mi->connection,MPD_TABLE_ALBUM,artist);
115 while (( string = mpd_getNextAlbum(mi->connection)) != NULL)
117 data = mpd_new_data_struct_append(data);
118 data->type = MPD_DATA_TYPE_TAG;
119 data->tag_type = MPD_TAG_ITEM_ALBUM;
120 data->tag = string;
122 mpd_finishCommand(mi->connection);
124 /* unlock */
125 mpd_unlock_conn(mi);
126 if(data == NULL)
128 return NULL;
130 return mpd_data_get_first(data);
133 MpdData * mpd_database_get_complete(MpdObj *mi)
135 MpdData *data = NULL;
136 mpd_InfoEntity *ent = NULL;
137 if(!mpd_check_connected(mi))
139 debug_printf(DEBUG_WARNING,"not connected\n");
140 return NULL;
142 if(mpd_lock_conn(mi))
144 debug_printf(DEBUG_ERROR,"lock failed\n");
145 return NULL;
147 mpd_sendListallInfoCommand(mi->connection, "/");
148 while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
151 if (ent->type == MPD_INFO_ENTITY_TYPE_SONG)
153 data = mpd_new_data_struct_append(data);
154 data->type = MPD_DATA_TYPE_SONG;
155 data->song = ent->info.song;
156 ent->info.song = NULL;
158 mpd_freeInfoEntity(ent);
160 mpd_finishCommand(mi->connection);
162 /* unlock */
163 mpd_unlock_conn(mi);
164 if(data == NULL)
166 return NULL;
168 return mpd_data_get_first(data);
171 int mpd_database_delete_playlist(MpdObj *mi,const char *path)
173 if(path == NULL)
175 debug_printf(DEBUG_WARNING, "path == NULL");
176 return MPD_ARGS_ERROR;
178 if(!mpd_check_connected(mi))
180 debug_printf(DEBUG_WARNING,"not connected\n");
181 return MPD_NOT_CONNECTED;
183 if(mpd_lock_conn(mi))
185 debug_printf(DEBUG_ERROR,"lock failed\n");
186 return MPD_LOCK_FAILED;
189 mpd_sendRmCommand(mi->connection,path);
190 mpd_finishCommand(mi->connection);
192 /* unlock */
193 mpd_unlock_conn(mi);
194 return MPD_OK;
197 int mpd_database_save_playlist(MpdObj *mi,const char *name)
199 if(name == NULL || !strlen(name))
201 debug_printf(DEBUG_WARNING, "mpd_playlist_save: name != NULL and strlen(name) > 0 failed");
202 return MPD_ARGS_ERROR;
204 if(!mpd_check_connected(mi))
206 debug_printf(DEBUG_WARNING,"mpd_playlist_save: not connected\n");
207 return MPD_NOT_CONNECTED;
209 if(mpd_lock_conn(mi))
211 debug_printf(DEBUG_ERROR,"mpd_playlist_save: lock failed\n");
212 return MPD_LOCK_FAILED;
215 mpd_sendSaveCommand(mi->connection,name);
216 mpd_finishCommand(mi->connection);
217 if(mi->connection->error == MPD_ERROR_ACK && mi->connection->errorCode == MPD_ACK_ERROR_EXIST)
219 mpd_clearError(mi->connection);
220 mpd_unlock_conn(mi);
221 return MPD_DATABASE_PLAYLIST_EXIST;
224 /* unlock */
225 mpd_unlock_conn(mi);
226 return MPD_OK;
229 /* "hack" to keep the compiler happy */
230 typedef int (* QsortCompare)(const void *a, const void *b);
232 static int compa(char **a,const char **b)
234 char *c =*a;
235 char *d =(char*)*b;
236 #ifndef NO_SMART_SORT
237 if(!strncasecmp(c, "The ",4) && strlen(c) > 4)
239 c = &c[4];
241 if(!strncasecmp(d, "The ",4) && strlen(d) > 4)
243 d = &d[4];
245 #endif
247 return strcasecmp(c,d);
250 MpdData *mpd_misc_sort_tag_list(MpdData *data)
252 char **array;
253 MpdData *test;
254 int i=0;
255 int length=0;
256 test = data = mpd_data_get_first(data);
259 length++;
260 test = mpd_data_get_next_real(test, FALSE);
261 }while(test != NULL);
262 array = malloc(length*sizeof(char*));
263 test = data;
267 array[i] = test->tag;
268 test = mpd_data_get_next_real(test, FALSE);
269 i++;
270 }while(test != NULL);
272 qsort(array,length,sizeof(char *),(QsortCompare)compa);
274 /* reset list */
275 test = mpd_data_get_first(data);
276 i=0;
279 test->tag = array[i];
280 test = mpd_data_get_next_real(test, FALSE);
281 i++;
282 }while(test != NULL);
283 free(array);
284 return mpd_data_get_first(data);
287 /* should be called mpd_database_find */
288 MpdData * mpd_database_find(MpdObj *mi, int table,const char *string, int exact)
290 MpdData *data = NULL;
291 /* MpdData *artist = NULL;
292 MpdData *album = NULL;
293 */ mpd_InfoEntity *ent = NULL;
294 if(!mpd_check_connected(mi))
296 debug_printf(DEBUG_WARNING,"not connected\n");
297 return NULL;
299 if(mpd_lock_conn(mi))
301 debug_printf(DEBUG_WARNING,"lock failed\n");
302 return NULL;
304 if(exact)
306 mpd_sendFindCommand(mi->connection,table,string);
308 else
310 mpd_sendSearchCommand(mi->connection, table,string);
312 while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
314 data = mpd_new_data_struct_append(data);
315 /* mpd_sendSearch|Find only returns songs */
317 if(ent->type == MPD_INFO_ENTITY_TYPE_DIRECTORY)
319 data->type = MPD_DATA_TYPE_DIRECTORY;
320 data->directory = ent->info.directory->path;
321 ent->info.directory->path = NULL;
323 else*/ if (ent->type == MPD_INFO_ENTITY_TYPE_SONG)
325 data->type = MPD_DATA_TYPE_SONG;
326 data->song = ent->info.song;
327 ent->info.song = NULL;
328 /* This is something the client can and should do */
329 /* if(data->song->artist != NULL)
331 int found = FALSE;
332 if(artist != NULL)
334 MpdData *fartist = mpd_data_get_first(artist);
336 if( (fartist->type == MPD_DATA_TYPE_TAG) && (fartist->tag_type == MPD_TAG_ITEM_ARTIST))
338 if(fartist->tag == NULL)
340 printf("crap this should'nt be \n");
342 if(!strcmp(fartist->tag, data->song->artist))
344 found = TRUE;
347 fartist = mpd_data_get_next_real(fartist, FALSE);
348 }while(fartist && !found);
350 if(!found)
352 artist= mpd_new_data_struct_append(artist);
353 artist->type = MPD_DATA_TYPE_TAG;
354 artist->tag_type = MPD_TAG_ITEM_ARTIST;
355 artist->tag = strdup(data->song->artist);
358 if(data->song->album != NULL)
360 int found = FALSE;
361 if(album != NULL)
363 MpdData *falbum = mpd_data_get_first(album);
365 if( (falbum->type == MPD_DATA_TYPE_TAG) && (falbum->tag_type == MPD_TAG_ITEM_ALBUM))
367 if(falbum->tag == NULL)
369 printf("crap this should'nt be \n");
371 if(!strcmp(falbum->tag, data->song->album))
373 found = TRUE;
376 falbum = mpd_data_get_next_real(falbum, FALSE);
377 }while(falbum && !found);
379 if(!found)
381 album = mpd_new_data_struct_append(album);
382 album->type = MPD_DATA_TYPE_TAG;
383 album->tag_type = MPD_TAG_ITEM_ALBUM;
384 album->tag = strdup(data->song->album);
390 else if (ent->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE)
392 data->type = MPD_DATA_TYPE_PLAYLIST;
393 data->playlist = ent->info.playlistFile->path;
394 ent->info.playlistFile->path = NULL;
398 mpd_freeInfoEntity(ent);
400 mpd_finishCommand(mi->connection);
402 /* unlock */
403 mpd_unlock_conn(mi);
404 if(data == NULL)
406 return NULL;
408 data = mpd_data_get_first(data);
409 /* prepend the album then artists*/
410 /* if(album != NULL)
412 if(data){
413 data = mpd_data_concatenate( album, data);
414 }else{
415 data = album;
418 if(artist != NULL)
420 if(data) {
421 album = mpd_data_concatenate( artist, data );
422 }else{
423 data = artist;
427 return mpd_data_get_first(data);
430 MpdData * mpd_database_get_directory(MpdObj *mi,const char *path)
432 MpdData *data = NULL;
433 mpd_InfoEntity *ent = NULL;
434 if(!mpd_check_connected(mi))
436 debug_printf(DEBUG_WARNING,"not connected\n");
437 return NULL;
439 if(path == NULL)
441 path = "/";
443 if(mpd_lock_conn(mi))
445 debug_printf(DEBUG_WARNING,"lock failed\n");
446 return NULL;
449 mpd_sendLsInfoCommand(mi->connection,path);
450 while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
452 data = mpd_new_data_struct_append(data);
453 if(ent->type == MPD_INFO_ENTITY_TYPE_DIRECTORY)
455 data->type = MPD_DATA_TYPE_DIRECTORY;
456 data->directory = ent->info.directory->path;
457 ent->info.directory->path = NULL;
459 else if (ent->type == MPD_INFO_ENTITY_TYPE_SONG)
461 data->type = MPD_DATA_TYPE_SONG;
462 data->song = ent->info.song;
463 ent->info.song = NULL;
465 else if (ent->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE)
467 data->type = MPD_DATA_TYPE_PLAYLIST;
468 data->playlist = ent->info.playlistFile;
469 ent->info.playlistFile= NULL;
472 mpd_freeInfoEntity(ent);
474 mpd_finishCommand(mi->connection);
476 /* unlock */
477 mpd_unlock_conn(mi);
478 if(data == NULL)
480 return NULL;
482 return mpd_data_get_first(data);
485 MpdData *mpd_database_get_playlist_content(MpdObj *mi,const char *playlist)
487 MpdData *data = NULL;
488 mpd_InfoEntity *ent = NULL;
489 if(!mpd_check_connected(mi))
491 debug_printf(DEBUG_WARNING,"not connected\n");
492 return NULL;
494 if(!mpd_server_check_version(mi, 0,12,0))
496 debug_printf(DEBUG_WARNING, "only works with mpd higher then 0.12.0");
497 return NULL;
499 if(mpd_server_check_command_allowed(mi, "listplaylistinfo") != MPD_SERVER_COMMAND_ALLOWED)
501 debug_printf(DEBUG_WARNING, "Listing playlist content not supported or allowed");
502 return NULL;
504 if(mpd_lock_conn(mi))
506 debug_printf(DEBUG_WARNING,"lock failed\n");
507 return NULL;
509 mpd_sendListPlaylistInfoCommand(mi->connection, playlist);
510 while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
512 data = mpd_new_data_struct_append( data );
513 if(ent->type == MPD_INFO_ENTITY_TYPE_DIRECTORY)
515 data->type = MPD_DATA_TYPE_DIRECTORY;
516 data->directory = ent->info.directory->path;
517 ent->info.directory->path = NULL;
519 else if (ent->type == MPD_INFO_ENTITY_TYPE_SONG)
521 data->type = MPD_DATA_TYPE_SONG;
522 data->song = ent->info.song;
523 ent->info.song = NULL;
525 else if (ent->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE)
527 data->type = MPD_DATA_TYPE_PLAYLIST;
528 data->playlist = ent->info.playlistFile;
529 ent->info.playlistFile= NULL;
532 mpd_freeInfoEntity(ent);
534 mpd_finishCommand(mi->connection);
536 /* unlock */
537 mpd_unlock_conn(mi);
538 if(data == NULL)
540 return NULL;
542 return mpd_data_get_first(data);
545 * @param mi A #MpdObj
546 * @param path an Path to a file
548 * Grabs the song info for a single file. Make sure you pass an url to a song
549 * and not a directory, that might result in strange behauviour.
551 * @returns a #mpd_Song
553 mpd_Song * mpd_database_get_fileinfo(MpdObj *mi,const char *path)
555 mpd_Song *song = NULL;
556 mpd_InfoEntity *ent = NULL;
558 * Check path for availibility and length
560 if(path == NULL || path[0] == '\0')
562 debug_printf(DEBUG_ERROR, "path == NULL || strlen(path) == 0");
563 return NULL;
565 if(!mpd_check_connected(mi))
567 debug_printf(DEBUG_ERROR, "Not Connected\n");
568 return NULL;
570 /* lock, so we can work on mi->connection */
571 if(mpd_lock_conn(mi) != MPD_OK)
573 debug_printf(DEBUG_ERROR, "Failed to lock connection");
574 return NULL;
576 /* send the request */
577 mpd_sendListallInfoCommand(mi->connection, path);
578 /* get the first (and only) result */
579 ent = mpd_getNextInfoEntity(mi->connection);
580 /* finish and clean up libmpdclient */
581 mpd_finishCommand(mi->connection);
582 /* unlock again */
583 if(mpd_unlock_conn(mi))
585 if(ent) mpd_freeInfoEntity(ent);
586 debug_printf(DEBUG_ERROR, "Failed to unlock");
587 return NULL;
590 if(ent == NULL)
592 debug_printf(DEBUG_ERROR, "Failed to grab song from mpd\n");
593 return NULL;
596 if(ent->type != MPD_INFO_ENTITY_TYPE_SONG)
598 mpd_freeInfoEntity(ent);
599 debug_printf(DEBUG_ERROR, "Failed to grab correct song type from mpd, path might not be a file\n");
600 return NULL;
602 /* get the song */
603 song = ent->info.song;
604 /* remove reference to song from the entity */
605 ent->info.song = NULL;
606 /* free the entity */
607 mpd_freeInfoEntity(ent);
609 return song;
613 void mpd_database_search_field_start(MpdObj *mi, mpd_TagItems field)
616 * Check argument
618 if(mi == NULL || field >= MPD_TAG_NUM_OF_ITEM_TYPES || field < 0)
620 debug_printf(DEBUG_ERROR, "Argument error");
621 return ;
623 if(!mpd_check_connected(mi))
625 debug_printf(DEBUG_ERROR, "Not Connected\n");
626 return ;
628 if(!mpd_server_check_version(mi, 0,12,0))
630 debug_printf(DEBUG_ERROR, "Advanced field list requires mpd 0.12.0 or higher");
631 return ;
633 /* lock, so we can work on mi->connection */
634 if(mpd_lock_conn(mi) != MPD_OK)
636 debug_printf(DEBUG_ERROR, "Failed to lock connection");
637 return ;
639 mpd_startFieldSearch(mi->connection, field);
640 /* Set search type */
641 mi->search_type = MPD_SEARCH_TYPE_LIST;
642 mi->search_field = field;
643 /* unlock, let the error handler handle any possible error.
645 mpd_unlock_conn(mi);
646 return;
656 * @param mi A #MpdObj
657 * @param exact a boolean indicating if the search is fuzzy or exact
659 * Starts a search, you can add "constraints" by calling mpd_database_search_add_constraint
661 * This function requires mpd 0.12.0 or higher
664 void mpd_database_search_start(MpdObj *mi, int exact)
667 * Check argument
669 if(mi == NULL || exact > 1 || exact < 0)
671 debug_printf(DEBUG_ERROR, "Argument error");
672 return ;
674 if(!mpd_check_connected(mi))
676 debug_printf(DEBUG_ERROR, "Not Connected\n");
677 return ;
679 if(!mpd_server_check_version(mi, 0,12,0))
681 debug_printf(DEBUG_ERROR, "Advanced search requires mpd 0.12.0 or higher");
682 return ;
684 /* lock, so we can work on mi->connection */
685 if(mpd_lock_conn(mi) != MPD_OK)
687 debug_printf(DEBUG_ERROR, "Failed to lock connection");
688 return ;
690 mpd_startSearch(mi->connection, exact);
691 /* Set search type */
692 mi->search_type = (exact)? MPD_SEARCH_TYPE_FIND:MPD_SEARCH_TYPE_SEARCH;
693 /* unlock, let the error handler handle any possible error.
695 mpd_unlock_conn(mi);
696 return;
699 * @param mi A #MpdObj
700 * @param field A #mpd_TagItems
702 * Adds a constraint to the search
704 void mpd_database_search_add_constraint(MpdObj *mi, mpd_TagItems field, const char *value)
706 if(mi == NULL || value == NULL )
708 debug_printf(DEBUG_ERROR,"Failed to parse arguments");
709 return;
711 if(mi->search_type == MPD_SEARCH_TYPE_NONE)
713 debug_printf(DEBUG_ERROR, "No search to constraint");
714 return;
716 if(!mpd_check_connected(mi))
718 debug_printf(DEBUG_ERROR, "Not Connected\n");
719 return ;
721 if(!mpd_server_check_version(mi, 0,12,0))
723 debug_printf(DEBUG_ERROR, "Advanced search requires mpd 0.12.0 or higher");
724 return ;
726 /* lock, so we can work on mi->connection */
727 if(mpd_lock_conn(mi) != MPD_OK)
729 debug_printf(DEBUG_ERROR, "Failed to lock connection");
730 return ;
732 mpd_addConstraintSearch(mi->connection, field, value);
733 /* unlock, let the error handler handle any possible error.
735 mpd_unlock_conn(mi);
736 return;
739 MpdData * mpd_database_search_commit(MpdObj *mi)
741 mpd_InfoEntity *ent = NULL;
742 MpdData *data = NULL;
743 if(!mpd_check_connected(mi))
745 debug_printf(DEBUG_WARNING,"not connected\n");
746 return NULL;
748 if(mi->search_type == MPD_SEARCH_TYPE_NONE)
750 debug_printf(DEBUG_ERROR, "no search in progress to commit");
751 return NULL;
753 if(mpd_lock_conn(mi))
755 debug_printf(DEBUG_ERROR,"lock failed\n");
756 return NULL;
758 mpd_commitSearch(mi->connection);
759 if(mi->search_type == MPD_SEARCH_TYPE_LIST)
761 char *string = NULL;
762 while((string = mpd_getNextTag(mi->connection, mi->search_field)))
764 data = mpd_new_data_struct_append(data);
765 data->type = MPD_DATA_TYPE_TAG;
766 data->tag_type = mi->search_field;
767 data->tag = string;
770 else
772 while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
774 if(ent->type == MPD_INFO_ENTITY_TYPE_SONG)
776 data = mpd_new_data_struct_append(data);
777 data->type = MPD_DATA_TYPE_SONG;
778 data->song = ent->info.song;
779 ent->info.song = NULL;
781 mpd_freeInfoEntity(ent);
784 mpd_finishCommand(mi->connection);
786 * reset search type
788 mi->search_type = MPD_SEARCH_TYPE_NONE;
789 mi->search_field = MPD_TAG_ITEM_ARTIST;
790 /* unlock */
791 if(mpd_unlock_conn(mi))
793 debug_printf(DEBUG_ERROR, "Failed to unlock connection");
794 if(data)mpd_data_free(data);
795 return NULL;
797 if(data == NULL)
799 return NULL;
801 return mpd_data_get_first(data);
805 * @param mi A #MpdObj
807 * Starts a search, you can add "constraints" by calling mpd_database_search_add_constraint
808 * to get the result call mpd_database_search_stats_commit
810 * This function requires mpd 0.13.0 or higher
813 void mpd_database_search_stats_start(MpdObj *mi)
816 * Check argument
818 if(mi == NULL)
820 debug_printf(DEBUG_ERROR, "Argument error");
821 return ;
823 if(!mpd_check_connected(mi))
825 debug_printf(DEBUG_ERROR, "Not Connected\n");
826 return ;
828 if(!mpd_server_check_version(mi, 0,13,0))
830 debug_printf(DEBUG_ERROR, "Advanced search requires mpd 0.13.0 or higher");
831 return ;
833 /* lock, so we can work on mi->connection */
834 if(mpd_lock_conn(mi) != MPD_OK)
836 debug_printf(DEBUG_ERROR, "Failed to lock connection");
837 return ;
839 mpd_startStatsSearch(mi->connection);
840 /* Set search type */
841 mi->search_type = MPD_SEARCH_TYPE_STATS;
842 /* unlock, let the error handler handle any possible error.
844 mpd_unlock_conn(mi);
845 return;
848 MpdDBStats * mpd_database_search_stats_commit(MpdObj *mi)
850 MpdDBStats *data = NULL;
851 if(!mpd_check_connected(mi))
853 debug_printf(DEBUG_WARNING,"not connected\n");
854 return NULL;
856 if(mi->search_type != MPD_SEARCH_TYPE_STATS)
858 debug_printf(DEBUG_ERROR, "no/wrong search in progress to commit");
859 return NULL;
861 if(mpd_lock_conn(mi))
863 debug_printf(DEBUG_ERROR,"lock failed\n");
864 return NULL;
866 mpd_commitSearch(mi->connection);
868 data = (MpdDBStats *) mpd_getSearchStats(mi->connection);
869 /* unlock */
870 if(mpd_unlock_conn(mi))
872 debug_printf(DEBUG_ERROR, "Failed to unlock connection");
873 if(data)mpd_freeSearchStats((mpd_SearchStats *)data);
874 return NULL;
876 if(data == NULL)
878 return NULL;
880 return data;
883 void mpd_database_search_free_stats(MpdDBStats *data)
885 mpd_freeSearchStats(data);
888 void mpd_database_playlist_clear(MpdObj *mi, const char *path)
890 if(!path )
891 return;
892 if (!mpd_check_connected(mi)) {
893 debug_printf(DEBUG_WARNING, "not connected\n");
894 return;
896 if (mpd_status_check(mi) != MPD_OK) {
897 debug_printf(DEBUG_WARNING, "Failed to get status\n");
898 return;
900 if(mpd_lock_conn(mi))
902 return ;
905 mpd_sendPlaylistClearCommand(mi->connection, (char *)path);
906 mpd_finishCommand(mi->connection);
908 mpd_unlock_conn(mi);
916 void mpd_database_playlist_list_delete(MpdObj *mi, const char *path, int pos)
918 if(!path )
919 return;
920 if (!mpd_check_connected(mi)) {
921 debug_printf(DEBUG_WARNING, "not connected\n");
922 return;
924 if (mpd_status_check(mi) != MPD_OK) {
925 debug_printf(DEBUG_WARNING, "Failed to get status\n");
926 return;
928 if(mpd_lock_conn(mi))
930 return ;
933 mpd_sendPlaylistDeleteCommand(mi->connection, (char *)path,pos);
934 mpd_finishCommand(mi->connection);
936 mpd_unlock_conn(mi);
938 void mpd_database_playlist_list_add(MpdObj *mi, const char *path, const char *file)
940 if(!path )
941 return;
942 if (!mpd_check_connected(mi)) {
943 debug_printf(DEBUG_WARNING, "not connected\n");
944 return;
946 if (mpd_status_check(mi) != MPD_OK) {
947 debug_printf(DEBUG_WARNING, "Failed to get status\n");
948 return;
950 if(mpd_lock_conn(mi))
952 return ;
955 mpd_sendPlaylistAddCommand(mi->connection, (char *)path,(char *)file);
956 mpd_finishCommand(mi->connection);
958 mpd_unlock_conn(mi);
961 MpdData * mpd_database_get_directory_recursive(MpdObj *mi, const char *path)
963 MpdData *data = NULL;
964 mpd_InfoEntity *ent = NULL;
965 if(!mpd_check_connected(mi))
967 debug_printf(DEBUG_WARNING,"not connected\n");
968 return NULL;
970 if(path == '\0' || path[0] == '\0')
972 debug_printf(DEBUG_ERROR, "argumant invalid\n");
973 return NULL;
975 if(mpd_lock_conn(mi))
977 debug_printf(DEBUG_ERROR,"lock failed\n");
978 return NULL;
980 mpd_sendListallInfoCommand(mi->connection,path);
981 while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
984 if (ent->type == MPD_INFO_ENTITY_TYPE_SONG)
986 data = mpd_new_data_struct_append(data);
987 data->type = MPD_DATA_TYPE_SONG;
988 data->song = ent->info.song;
989 ent->info.song = NULL;
991 mpd_freeInfoEntity(ent);
993 mpd_finishCommand(mi->connection);
995 /* unlock */
996 mpd_unlock_conn(mi);
997 if(data == NULL)
999 return NULL;
1001 return mpd_data_get_first(data);
1003 void mpd_database_playlist_rename(MpdObj *mi, const char *old_name, const char *new_name)
1005 if(!new_name || !old_name)
1007 debug_printf(DEBUG_ERROR, "old != NULL && new != NULL failed");
1008 return;
1010 if (!mpd_check_connected(mi)) {
1011 debug_printf(DEBUG_WARNING, "not connected\n");
1012 return;
1014 if (mpd_status_check(mi) != MPD_OK) {
1015 debug_printf(DEBUG_WARNING, "Failed to get status\n");
1016 return;
1018 if(mpd_lock_conn(mi))
1020 return ;
1023 mpd_sendRenameCommand(mi->connection, (char *)old_name,(char *)new_name);
1024 mpd_finishCommand(mi->connection);
1026 mpd_unlock_conn(mi);
1029 int mpd_database_playlist_move(MpdObj *mi, const char *playlist, int old_pos, int new_pos)
1031 if(!mpd_check_connected(mi))
1033 debug_printf(DEBUG_WARNING,"not connected\n");
1034 return MPD_NOT_CONNECTED;
1036 if(mpd_lock_conn(mi))
1038 debug_printf(DEBUG_ERROR,"lock failed\n");
1039 return MPD_LOCK_FAILED;
1042 mpd_sendPlaylistMoveCommand(mi->connection,(char *)playlist,old_pos, new_pos);
1043 mpd_finishCommand(mi->connection);
1045 /* unlock */
1046 mpd_unlock_conn(mi);
1047 return MPD_OK;
1051 MpdData * mpd_database_playlist_list(MpdObj *mi)
1053 MpdData *data = NULL;
1054 mpd_InfoEntity *ent = NULL;
1055 if(!mpd_check_connected(mi))
1057 debug_printf(DEBUG_WARNING,"not connected\n");
1058 return NULL;
1060 if(mpd_lock_conn(mi))
1062 debug_printf(DEBUG_ERROR,"lock failed\n");
1063 return NULL;
1065 if(mpd_server_check_command_allowed(mi, "listplaylists") == MPD_SERVER_COMMAND_ALLOWED)
1067 mpd_sendListPlaylistsCommand(mi->connection);
1069 else
1071 mpd_sendLsInfoCommand (mi->connection ,"/");
1073 while (( ent = mpd_getNextInfoEntity(mi->connection)) != NULL)
1076 if (ent->type == MPD_INFO_ENTITY_TYPE_PLAYLISTFILE)
1078 data = mpd_new_data_struct_append(data);
1079 data->type = MPD_DATA_TYPE_PLAYLIST;
1080 data->playlist= ent->info.playlistFile;
1081 ent->info.playlistFile = NULL;
1083 mpd_freeInfoEntity(ent);
1085 mpd_finishCommand(mi->connection);
1087 /* unlock */
1088 mpd_unlock_conn(mi);
1089 if(data == NULL)
1091 return NULL;
1093 return mpd_data_get_first(data);