1 /***************************************************************************
2 * Copyright (C) 2008-2009 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
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 *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
31 const char *MPD::Message::PartOfSongsAdded
= "Only part of requested songs' list added to playlist!";
32 const char *MPD::Message::FullPlaylist
= "Playlist is full!";
33 const char *MPD::Message::FunctionDisabledFilteringEnabled
= "Function disabled due to enabled filtering in playlist";
35 MPD::Connection::Connection() : itsConnection(0),
36 isCommandsListEnabled(0),
37 itsMaxPlaylistLength(-1),
51 MPD::Connection::~Connection()
54 mpd_connection_free(itsConnection
);
56 mpd_stats_free(itsStats
);
58 mpd_status_free(itsOldStatus
);
60 mpd_status_free(itsCurrentStatus
);
63 bool MPD::Connection::Connect()
67 itsConnection
= mpd_connection_new(itsHost
.c_str(), itsPort
, itsTimeout
*1000 /* timeout is in ms now */);
70 if (!itsPassword
.empty())
72 itsFD
= mpd_connection_get_fd(itsConnection
);
73 supportsIdle
= isIdleEnabled
&& Version() > 13;
74 // in UpdateStatus() we compare it to itsElapsedTimer[0],
75 // and for the first time it has always evaluate to true
76 // so we need it to be zero at this point
77 itsElapsedTimer
[1] = 0;
78 return !CheckForErrors();
81 bool MPD::Connection::Connected() const
86 void MPD::Connection::Disconnect()
89 mpd_connection_free(itsConnection
);
91 mpd_stats_free(itsStats
);
93 mpd_status_free(itsOldStatus
);
95 mpd_status_free(itsCurrentStatus
);
101 isCommandsListEnabled
= 0;
102 itsMaxPlaylistLength
= -1;
105 float MPD::Connection::Version() const
109 const unsigned *version
= mpd_connection_get_server_version(itsConnection
);
110 return version
[1] + version
[2]*0.1;
113 void MPD::Connection::SetHostname(const std::string
&host
)
115 size_t at
= host
.find("@");
116 if (at
!= std::string::npos
)
118 itsPassword
= host
.substr(0, at
);
119 itsHost
= host
.substr(at
+1);
125 bool MPD::Connection::SendPassword()
128 assert(!isCommandsListEnabled
);
129 mpd_run_password(itsConnection
, itsPassword
.c_str());
130 return !CheckForErrors();
133 void MPD::Connection::SetStatusUpdater(StatusUpdater updater
, void *data
)
135 itsUpdater
= updater
;
136 itsStatusUpdaterUserdata
= data
;
139 void MPD::Connection::SetErrorHandler(ErrorHandler handler
, void *data
)
141 itsErrorHandler
= handler
;
142 itsErrorHandlerUserdata
= data
;
145 void MPD::Connection::GoIdle()
147 if (supportsIdle
&& !isIdle
&& mpd_send_idle(itsConnection
))
151 int MPD::Connection::GoBusy()
153 if (isIdle
&& mpd_send_noidle(itsConnection
))
156 return mpd_recv_idle(itsConnection
, 1);
161 void MPD::Connection::UpdateStatus()
171 idle_mask
= GoBusy();
176 // count local elapsed time as we don't receive
177 // this from mpd while being in idle mode
178 time(&itsElapsedTimer
[1]);
179 double diff
= difftime(itsElapsedTimer
[1], itsElapsedTimer
[0]);
180 if (diff
>= 1.0 && Mpd
.GetState() == psPlay
)
182 time(&itsElapsedTimer
[0]);
184 StatusChanges changes
;
185 changes
.ElapsedTime
= 1;
187 itsUpdater(this, changes
, itsErrorHandlerUserdata
);
199 mpd_status_free(itsOldStatus
);
201 itsOldStatus
= itsCurrentStatus
;
202 itsCurrentStatus
= 0;
204 itsCurrentStatus
= mpd_run_status(itsConnection
);
206 if (!itsMaxPlaylistLength
)
207 itsMaxPlaylistLength
= GetPlaylistLength();
209 if (CheckForErrors())
212 if (itsCurrentStatus
&& itsUpdater
)
216 // sync local elapsed time counter with mpd
217 unsigned old_elapsed
= itsElapsed
;
218 itsElapsed
= mpd_status_get_elapsed_time(itsCurrentStatus
);
219 itsChanges
.ElapsedTime
= itsElapsed
!= old_elapsed
;
220 time(&itsElapsedTimer
[0]);
223 itsElapsed
= mpd_status_get_elapsed_time(itsCurrentStatus
);
227 itsChanges
.Playlist
= 1;
228 itsChanges
.SongID
= 1;
229 itsChanges
.Database
= 1;
230 itsChanges
.DBUpdating
= 1;
231 itsChanges
.Volume
= 1;
232 itsChanges
.ElapsedTime
= 1;
233 itsChanges
.Crossfade
= 1;
234 itsChanges
.Random
= 1;
235 itsChanges
.Repeat
= 1;
236 itsChanges
.Single
= 1;
237 itsChanges
.Consume
= 1;
238 itsChanges
.PlayerState
= 1;
239 itsChanges
.StatusFlags
= 1;
240 itsChanges
.Outputs
= 1;
246 itsChanges
.Playlist
= idle_mask
& MPD_IDLE_QUEUE
;
247 itsChanges
.Database
= idle_mask
& MPD_IDLE_DATABASE
;
248 itsChanges
.DBUpdating
= idle_mask
& MPD_IDLE_UPDATE
;
249 itsChanges
.Volume
= idle_mask
& MPD_IDLE_MIXER
;
250 itsChanges
.StatusFlags
= idle_mask
& (MPD_IDLE_OPTIONS
| MPD_IDLE_UPDATE
);
251 itsChanges
.Outputs
= idle_mask
& MPD_IDLE_OUTPUT
;
255 itsChanges
.Playlist
= mpd_status_get_queue_version(itsOldStatus
)
256 != mpd_status_get_queue_version(itsCurrentStatus
);
258 itsChanges
.ElapsedTime
= mpd_status_get_elapsed_time(itsOldStatus
)
259 != mpd_status_get_elapsed_time(itsCurrentStatus
);
261 itsChanges
.Database
= mpd_status_get_update_id(itsOldStatus
)
262 && !mpd_status_get_update_id(itsCurrentStatus
);
264 itsChanges
.DBUpdating
= mpd_status_get_update_id(itsOldStatus
)
265 != mpd_status_get_update_id(itsCurrentStatus
);
267 itsChanges
.Volume
= mpd_status_get_volume(itsOldStatus
)
268 != mpd_status_get_volume(itsCurrentStatus
);
270 itsChanges
.StatusFlags
= itsChanges
.Repeat
273 || itsChanges
.Consume
274 || itsChanges
.Crossfade
275 || itsChanges
.DBUpdating
;
277 // there is no way to determine if the output has changed or not
278 // from mpd status, it's possible only with idle notifications
279 itsChanges
.Outputs
= 0;
282 itsChanges
.SongID
= mpd_status_get_song_id(itsOldStatus
)
283 != mpd_status_get_song_id(itsCurrentStatus
);
285 itsChanges
.Crossfade
= mpd_status_get_crossfade(itsOldStatus
)
286 != mpd_status_get_crossfade(itsCurrentStatus
);
288 itsChanges
.Random
= mpd_status_get_random(itsOldStatus
)
289 != mpd_status_get_random(itsCurrentStatus
);
291 itsChanges
.Repeat
= mpd_status_get_repeat(itsOldStatus
)
292 != mpd_status_get_repeat(itsCurrentStatus
);
294 itsChanges
.Single
= mpd_status_get_single(itsOldStatus
)
295 != mpd_status_get_single(itsCurrentStatus
);
297 itsChanges
.Consume
= mpd_status_get_consume(itsOldStatus
)
298 != mpd_status_get_consume(itsCurrentStatus
);
300 itsChanges
.PlayerState
= mpd_status_get_state(itsOldStatus
)
301 != mpd_status_get_state(itsCurrentStatus
);
303 itsUpdater(this, itsChanges
, itsErrorHandlerUserdata
);
304 // status updater could invoke mpd commands that
305 // could fail se we need to check for errors
311 void MPD::Connection::UpdateStats()
315 assert(!isCommandsListEnabled
);
318 mpd_stats_free(itsStats
);
319 itsStats
= mpd_run_stats(itsConnection
);
323 bool MPD::Connection::UpdateDirectory(const std::string
&path
)
327 if (!isCommandsListEnabled
)
330 bool success
= mpd_run_update(itsConnection
, path
.c_str());
331 if (!supportsIdle
&& success
)
338 return mpd_send_update(itsConnection
, path
.c_str());
343 void MPD::Connection::Play()
347 if (!isCommandsListEnabled
)
350 mpd_run_play(itsConnection
);
355 mpd_send_play(itsConnection
);
359 void MPD::Connection::Play(int pos
)
363 if (!isCommandsListEnabled
)
366 mpd_run_play_pos(itsConnection
, pos
);
371 mpd_send_play_pos(itsConnection
, pos
);
375 void MPD::Connection::PlayID(int id
)
379 if (!isCommandsListEnabled
)
382 mpd_run_play_id(itsConnection
, id
);
387 mpd_send_play_id(itsConnection
, id
);
391 void MPD::Connection::Pause(bool state
)
395 if (!isCommandsListEnabled
)
398 mpd_run_pause(itsConnection
, state
);
403 mpd_send_pause(itsConnection
, state
);
407 void MPD::Connection::Toggle()
411 if (!isCommandsListEnabled
)
415 mpd_run_toggle_pause(itsConnection
);
417 mpd_run_play(itsConnection
);
423 mpd_send_toggle_pause(itsConnection
);
425 mpd_send_play(itsConnection
);
429 void MPD::Connection::Stop()
433 if (!isCommandsListEnabled
)
436 mpd_run_stop(itsConnection
);
441 mpd_send_stop(itsConnection
);
445 void MPD::Connection::Next()
449 if (!isCommandsListEnabled
)
452 mpd_run_next(itsConnection
);
457 mpd_send_next(itsConnection
);
461 void MPD::Connection::Prev()
465 if (!isCommandsListEnabled
)
468 mpd_run_previous(itsConnection
);
473 mpd_send_previous(itsConnection
);
477 void MPD::Connection::Move(unsigned from
, unsigned to
)
481 if (!isCommandsListEnabled
)
484 mpd_run_move(itsConnection
, from
, to
);
489 mpd_send_move(itsConnection
, from
, to
);
493 void MPD::Connection::Swap(unsigned from
, unsigned to
)
497 if (!isCommandsListEnabled
)
500 mpd_run_swap(itsConnection
, from
, to
);
505 mpd_send_swap(itsConnection
, from
, to
);
509 void MPD::Connection::Seek(unsigned where
)
513 if (!isCommandsListEnabled
)
516 mpd_run_seek_pos(itsConnection
, Mpd
.GetCurrentSongPos(), where
);
521 mpd_send_seek_pos(itsConnection
, Mpd
.GetCurrentSongPos(), where
);
525 void MPD::Connection::Shuffle()
529 if (!isCommandsListEnabled
)
532 mpd_run_shuffle(itsConnection
);
537 mpd_send_shuffle(itsConnection
);
541 void MPD::Connection::ClearPlaylist()
545 if (!isCommandsListEnabled
)
548 mpd_run_clear(itsConnection
);
553 mpd_send_clear(itsConnection
);
557 void MPD::Connection::ClearPlaylist(const std::string
&playlist
)
561 if (!isCommandsListEnabled
)
564 mpd_run_playlist_clear(itsConnection
, playlist
.c_str());
568 mpd_send_playlist_clear(itsConnection
, playlist
.c_str());
573 void MPD::Connection::AddToPlaylist(const std::string
&path
, const Song
&s
)
576 AddToPlaylist(path
, s
.GetFile());
579 void MPD::Connection::AddToPlaylist(const std::string
&path
, const std::string
&file
)
583 if (!isCommandsListEnabled
)
586 mpd_run_playlist_add(itsConnection
, path
.c_str(), file
.c_str());
591 mpd_send_playlist_add(itsConnection
, path
.c_str(), file
.c_str());
595 void MPD::Connection::Move(const std::string
&path
, int from
, int to
)
599 if (!isCommandsListEnabled
)
603 mpd_send_playlist_move(itsConnection
, path
.c_str(), from
, to
);
604 if (!isCommandsListEnabled
)
605 mpd_response_finish(itsConnection
);
608 bool MPD::Connection::Rename(const std::string
&from
, const std::string
&to
)
612 if (!isCommandsListEnabled
)
615 return mpd_run_rename(itsConnection
, from
.c_str(), to
.c_str());
620 return mpd_send_rename(itsConnection
, from
.c_str(), to
.c_str());
624 void MPD::Connection::GetPlaylistChanges(unsigned version
, SongList
&v
)
628 assert(!isCommandsListEnabled
);
630 v
.reserve(GetPlaylistLength());
632 mpd_send_queue_changes_meta(itsConnection
, version
);
633 while (mpd_song
*s
= mpd_recv_song(itsConnection
))
634 v
.push_back(new Song(s
, 1));
635 mpd_response_finish(itsConnection
);
639 MPD::Song
MPD::Connection::GetSong(const std::string
&path
)
643 assert(!isCommandsListEnabled
);
645 mpd_send_list_all_meta(itsConnection
, path
.c_str());
646 mpd_song
*s
= mpd_recv_song(itsConnection
);
647 mpd_response_finish(itsConnection
);
652 int MPD::Connection::GetCurrentSongPos() const
654 return itsCurrentStatus
&& isPlaying() ? mpd_status_get_song_pos(itsCurrentStatus
) : -1;
657 MPD::Song
MPD::Connection::GetCurrentSong()
659 assert(!isCommandsListEnabled
);
661 Song result
= Song(itsConnection
&& isPlaying() ? mpd_run_current_song(itsConnection
) : 0);
666 void MPD::Connection::GetPlaylistContent(const std::string
&path
, SongList
&v
)
670 assert(!isCommandsListEnabled
);
672 mpd_send_list_playlist_meta(itsConnection
, path
.c_str());
673 while (mpd_song
*s
= mpd_recv_song(itsConnection
))
674 v
.push_back(new Song(s
));
675 mpd_response_finish(itsConnection
);
679 void MPD::Connection::SetRepeat(bool mode
)
683 if (!isCommandsListEnabled
)
686 mpd_run_repeat(itsConnection
, mode
);
691 mpd_send_repeat(itsConnection
, mode
);
695 void MPD::Connection::SetRandom(bool mode
)
699 if (!isCommandsListEnabled
)
702 mpd_run_random(itsConnection
, mode
);
707 mpd_send_random(itsConnection
, mode
);
711 void MPD::Connection::SetSingle(bool mode
)
715 if (!isCommandsListEnabled
)
718 mpd_run_single(itsConnection
, mode
);
723 mpd_send_single(itsConnection
, mode
);
727 void MPD::Connection::SetConsume(bool mode
)
731 if (!isCommandsListEnabled
)
734 mpd_run_consume(itsConnection
, mode
);
739 mpd_send_consume(itsConnection
, mode
);
743 void MPD::Connection::SetVolume(unsigned vol
)
745 if (!itsConnection
|| vol
> 100)
747 assert(!isCommandsListEnabled
);
749 if (mpd_run_set_volume(itsConnection
, vol
) && !supportsIdle
)
753 std::string
MPD::Connection::GetReplayGainMode()
757 assert(!isCommandsListEnabled
);
759 if (!mpd_send_command(itsConnection
, "replay_gain_status", NULL
))
762 if (mpd_pair
*pair
= mpd_recv_pair_named(itsConnection
, "replay_gain_mode"))
764 result
= pair
->value
;
766 result
[0] = toupper(result
[0]);
767 mpd_return_pair(itsConnection
, pair
);
769 mpd_response_finish(itsConnection
);
773 void MPD::Connection::SetReplayGainMode(ReplayGainMode mode
)
790 FatalError("undefined value of ReplayGainMode!");
792 if (!isCommandsListEnabled
)
796 if (!mpd_send_command(itsConnection
, "replay_gain_mode", rg_mode
, NULL
))
798 if (!isCommandsListEnabled
)
799 mpd_response_finish(itsConnection
);
802 void MPD::Connection::SetCrossfade(unsigned crossfade
)
806 if (!isCommandsListEnabled
)
809 mpd_run_crossfade(itsConnection
, crossfade
);
814 mpd_send_crossfade(itsConnection
, crossfade
);
818 int MPD::Connection::AddSong(const std::string
&path
, int pos
)
823 if (GetPlaylistLength() < itsMaxPlaylistLength
)
825 if (!isCommandsListEnabled
)
830 mpd_send_add_id(itsConnection
, path
.c_str());
832 mpd_send_add_id_to(itsConnection
, path
.c_str(), pos
);
833 if (!isCommandsListEnabled
)
835 id
= mpd_recv_song_id(itsConnection
);
836 mpd_response_finish(itsConnection
);
841 else if (itsErrorHandler
)
842 itsErrorHandler(this, MPD_SERVER_ERROR_PLAYLIST_MAX
, Message::FullPlaylist
, itsErrorHandlerUserdata
);
846 int MPD::Connection::AddSong(const Song
&s
, int pos
)
848 return !s
.Empty() ? (AddSong((!s
.isFromDB() ? "file://" : "") + (s
.Localized() ? locale_to_utf_cpy(s
.GetFile()) : s
.GetFile()), pos
)) : -1;
851 void MPD::Connection::Add(const std::string
&path
)
855 if (!isCommandsListEnabled
)
858 mpd_run_add(itsConnection
, path
.c_str());
863 mpd_send_add(itsConnection
, path
.c_str());
867 bool MPD::Connection::AddRandomSongs(size_t number
)
869 if (!itsConnection
&& !number
)
871 assert(!isCommandsListEnabled
);
876 mpd_send_list_all(itsConnection
, "/");
877 while (mpd_pair
*item
= mpd_recv_pair_named(itsConnection
, "file"))
879 files
.push_back(item
->value
);
880 mpd_return_pair(itsConnection
, item
);
882 mpd_response_finish(itsConnection
);
884 if (number
> files
.size())
887 itsErrorHandler(this, 0, "Requested number of random songs is bigger than size of your library!", itsErrorHandlerUserdata
);
893 std::random_shuffle(files
.begin(), files
.end());
895 TagList::const_iterator it
= files
.begin()+rand()%(files
.size()-number
);
896 for (size_t i
= 0; i
< number
&& it
!= files
.end(); ++i
)
898 CommitCommandsList();
903 bool MPD::Connection::Delete(unsigned pos
)
907 if (!isCommandsListEnabled
)
911 bool result
= mpd_send_delete(itsConnection
, pos
);
912 if (!isCommandsListEnabled
)
913 result
= mpd_response_finish(itsConnection
);
917 bool MPD::Connection::DeleteID(unsigned id
)
921 if (!isCommandsListEnabled
)
925 bool result
= mpd_send_delete_id(itsConnection
, id
);
926 if (!isCommandsListEnabled
)
927 result
= mpd_response_finish(itsConnection
);
931 bool MPD::Connection::Delete(const std::string
&playlist
, unsigned pos
)
935 if (!isCommandsListEnabled
)
938 return mpd_run_playlist_delete(itsConnection
, playlist
.c_str(), pos
);
943 return mpd_send_playlist_delete(itsConnection
, playlist
.c_str(), pos
);
947 void MPD::Connection::StartCommandsList()
951 assert(!isCommandsListEnabled
);
953 mpd_command_list_begin(itsConnection
, 1);
954 isCommandsListEnabled
= 1;
957 bool MPD::Connection::CommitCommandsList()
961 assert(isCommandsListEnabled
);
963 mpd_command_list_end(itsConnection
);
964 mpd_response_finish(itsConnection
);
965 if (GetPlaylistLength() == itsMaxPlaylistLength
&& itsErrorHandler
)
966 itsErrorHandler(this, MPD_SERVER_ERROR_PLAYLIST_MAX
, Message::FullPlaylist
, itsErrorHandlerUserdata
);
967 isCommandsListEnabled
= 0;
968 bool result
= !CheckForErrors();
973 bool MPD::Connection::DeletePlaylist(const std::string
&name
)
977 if (!isCommandsListEnabled
)
980 return mpd_run_rm(itsConnection
, name
.c_str());
985 return mpd_send_rm(itsConnection
, name
.c_str());
989 bool MPD::Connection::SavePlaylist(const std::string
&name
)
993 assert(!isCommandsListEnabled
);
995 mpd_send_save(itsConnection
, name
.c_str());
996 mpd_response_finish(itsConnection
);
997 return !(mpd_connection_get_error(itsConnection
) == MPD_ERROR_SERVER
998 && mpd_connection_get_server_error(itsConnection
) == MPD_SERVER_ERROR_EXIST
);
1001 void MPD::Connection::GetPlaylists(TagList
&v
)
1006 GetDirectory("/", list
);
1007 for (ItemList::const_iterator it
= list
.begin(); it
!= list
.end(); ++it
)
1008 if (it
->type
== itPlaylist
)
1009 v
.push_back(it
->name
);
1013 void MPD::Connection::GetList(TagList
&v
, mpd_tag_type type
)
1017 assert(!isCommandsListEnabled
);
1019 mpd_search_db_tags(itsConnection
, type
);
1020 mpd_search_commit(itsConnection
);
1021 while (mpd_pair
*item
= mpd_recv_pair_tag(itsConnection
, type
))
1023 v
.push_back(item
->value
);
1024 mpd_return_pair(itsConnection
, item
);
1026 mpd_response_finish(itsConnection
);
1030 void MPD::Connection::StartSearch(bool exact_match
)
1033 mpd_search_db_songs(itsConnection
, exact_match
);
1036 void MPD::Connection::StartFieldSearch(mpd_tag_type item
)
1040 itsSearchedField
= item
;
1041 mpd_search_db_tags(itsConnection
, item
);
1045 void MPD::Connection::AddSearch(mpd_tag_type item
, const std::string
&str
) const
1047 // mpd version < 0.14.* doesn't support empty search constraints
1048 if (Version() < 14 && str
.empty())
1051 mpd_search_add_tag_constraint(itsConnection
, MPD_OPERATOR_DEFAULT
, item
, str
.c_str());
1054 void MPD::Connection::AddSearchAny(const std::string
&str
) const
1056 assert(!str
.empty());
1058 mpd_search_add_any_tag_constraint(itsConnection
, MPD_OPERATOR_DEFAULT
, str
.c_str());
1061 void MPD::Connection::AddSearchURI(const std::string
&str
) const
1063 assert(!str
.empty());
1065 mpd_search_add_uri_constraint(itsConnection
, MPD_OPERATOR_DEFAULT
, str
.c_str());
1068 void MPD::Connection::CommitSearch(SongList
&v
)
1072 assert(!isCommandsListEnabled
);
1074 mpd_search_commit(itsConnection
);
1075 while (mpd_song
*s
= mpd_recv_song(itsConnection
))
1076 v
.push_back(new Song(s
));
1077 mpd_response_finish(itsConnection
);
1081 void MPD::Connection::CommitSearch(TagList
&v
)
1085 assert(!isCommandsListEnabled
);
1087 mpd_search_commit(itsConnection
);
1088 while (mpd_pair
*tag
= mpd_recv_pair_tag(itsConnection
, itsSearchedField
))
1090 v
.push_back(tag
->value
);
1091 mpd_return_pair(itsConnection
, tag
);
1093 mpd_response_finish(itsConnection
);
1097 void MPD::Connection::GetDirectory(const std::string
&path
, ItemList
&v
)
1101 assert(!isCommandsListEnabled
);
1103 mpd_send_list_meta(itsConnection
, path
.c_str());
1104 while (mpd_entity
*item
= mpd_recv_entity(itsConnection
))
1107 switch (mpd_entity_get_type(item
))
1109 case MPD_ENTITY_TYPE_DIRECTORY
:
1110 it
.name
= mpd_directory_get_path(mpd_entity_get_directory(item
));
1111 it
.type
= itDirectory
;
1113 case MPD_ENTITY_TYPE_SONG
:
1114 it
.song
= new Song(mpd_song_dup(mpd_entity_get_song(item
)));
1117 case MPD_ENTITY_TYPE_PLAYLIST
:
1118 it
.name
= mpd_playlist_get_path(mpd_entity_get_playlist(item
));
1119 it
.type
= itPlaylist
;
1127 mpd_entity_free(item
);
1129 mpd_response_finish(itsConnection
);
1133 void MPD::Connection::GetDirectoryRecursive(const std::string
&path
, SongList
&v
)
1137 assert(!isCommandsListEnabled
);
1139 mpd_send_list_all_meta(itsConnection
, path
.c_str());
1140 while (mpd_song
*s
= mpd_recv_song(itsConnection
))
1141 v
.push_back(new Song(s
));
1142 mpd_response_finish(itsConnection
);
1146 void MPD::Connection::GetSongs(const std::string
&path
, SongList
&v
)
1150 assert(!isCommandsListEnabled
);
1152 mpd_send_list_meta(itsConnection
, path
.c_str());
1153 while (mpd_song
*s
= mpd_recv_song(itsConnection
))
1154 v
.push_back(new Song(s
));
1155 mpd_response_finish(itsConnection
);
1159 void MPD::Connection::GetDirectories(const std::string
&path
, TagList
&v
)
1163 assert(!isCommandsListEnabled
);
1165 mpd_send_list_meta(itsConnection
, path
.c_str());
1166 while (mpd_directory
*dir
= mpd_recv_directory(itsConnection
))
1168 v
.push_back(mpd_directory_get_path(dir
));
1169 mpd_directory_free(dir
);
1171 mpd_response_finish(itsConnection
);
1175 void MPD::Connection::GetOutputs(OutputList
&v
)
1179 assert(!isCommandsListEnabled
);
1181 mpd_send_outputs(itsConnection
);
1182 while (mpd_output
*output
= mpd_recv_output(itsConnection
))
1184 v
.push_back(std::make_pair(mpd_output_get_name(output
), mpd_output_get_enabled(output
)));
1185 mpd_output_free(output
);
1187 mpd_response_finish(itsConnection
);
1191 bool MPD::Connection::EnableOutput(int id
)
1195 if (!isCommandsListEnabled
)
1198 return mpd_run_enable_output(itsConnection
, id
);
1203 return mpd_send_enable_output(itsConnection
, id
);
1207 bool MPD::Connection::DisableOutput(int id
)
1211 if (!isCommandsListEnabled
)
1214 return mpd_run_disable_output(itsConnection
, id
);
1219 return mpd_send_disable_output(itsConnection
, id
);
1223 void MPD::Connection::GetURLHandlers(TagList
&v
)
1227 assert(!isCommandsListEnabled
);
1229 mpd_send_list_url_schemes(itsConnection
);
1230 while (mpd_pair
*handler
= mpd_recv_pair_named(itsConnection
, "handler"))
1232 v
.push_back(handler
->value
);
1233 mpd_return_pair(itsConnection
, handler
);
1235 mpd_response_finish(itsConnection
);
1239 void MPD::Connection::GetTagTypes(TagList
&v
)
1243 assert(!isCommandsListEnabled
);
1245 mpd_send_list_tag_types(itsConnection
);
1246 while (mpd_pair
*tag_type
= mpd_recv_pair_named(itsConnection
, "tagtype"))
1248 v
.push_back(tag_type
->value
);
1249 mpd_return_pair(itsConnection
, tag_type
);
1251 mpd_response_finish(itsConnection
);
1255 int MPD::Connection::CheckForErrors()
1258 if ((error_code
= mpd_connection_get_error(itsConnection
)) != MPD_ERROR_SUCCESS
)
1260 itsErrorMessage
= mpd_connection_get_error_message(itsConnection
);
1261 if (error_code
== MPD_ERROR_SERVER
)
1263 // this is to avoid setting too small max size as we check it before fetching current status
1264 // setting real max playlist length is in UpdateStatus()
1265 error_code
= mpd_connection_get_server_error(itsConnection
);
1266 if (error_code
== MPD_SERVER_ERROR_PLAYLIST_MAX
&& itsMaxPlaylistLength
== size_t(-1))
1267 itsMaxPlaylistLength
= 0;
1269 if (!mpd_connection_clear_error(itsConnection
))
1271 if (itsErrorHandler
)
1272 itsErrorHandler(this, error_code
, itsErrorMessage
.c_str(), itsErrorHandlerUserdata
);
1277 void MPD::FreeSongList(SongList
&l
)
1279 for (SongList::iterator i
= l
.begin(); i
!= l
.end(); ++i
)
1284 void MPD::FreeItemList(ItemList
&l
)
1286 for (ItemList::iterator i
= l
.begin(); i
!= l
.end(); ++i
)