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 ***************************************************************************/
33 const char *MPD::Message::PartOfSongsAdded
= "Only part of requested songs' list added to playlist!";
34 const char *MPD::Message::FullPlaylist
= "Playlist is full!";
35 const char *MPD::Message::FunctionDisabledFilteringEnabled
= "Function disabled due to enabled filtering in playlist";
37 Connection::Connection() : itsConnection(0),
38 isCommandsListEnabled(0),
39 itsMaxPlaylistLength(-1),
53 Connection::~Connection()
56 mpd_connection_free(itsConnection
);
58 mpd_stats_free(itsStats
);
60 mpd_status_free(itsOldStatus
);
62 mpd_status_free(itsCurrentStatus
);
65 bool Connection::Connect()
69 itsConnection
= mpd_connection_new(itsHost
.c_str(), itsPort
, itsTimeout
*1000 /* timeout is in ms now */);
72 if (!itsPassword
.empty())
74 itsFD
= mpd_connection_get_fd(itsConnection
);
75 supportsIdle
= isIdleEnabled
&& Version() > 13;
76 // in UpdateStatus() we compare it to itsElapsedTimer[0],
77 // and for the first time it has always evaluate to true
78 // so we need it to be zero at this point
79 itsElapsedTimer
[1] = 0;
80 return !CheckForErrors();
83 bool Connection::Connected() const
88 void Connection::Disconnect()
91 mpd_connection_free(itsConnection
);
93 mpd_stats_free(itsStats
);
95 mpd_status_free(itsOldStatus
);
97 mpd_status_free(itsCurrentStatus
);
100 itsCurrentStatus
= 0;
103 isCommandsListEnabled
= 0;
104 itsMaxPlaylistLength
= -1;
107 float Connection::Version() const
111 const unsigned *version
= mpd_connection_get_server_version(itsConnection
);
112 return version
[1] + version
[2]*0.1;
115 void Connection::SetHostname(const std::string
&host
)
117 size_t at
= host
.find("@");
118 if (at
!= std::string::npos
)
120 itsPassword
= host
.substr(0, at
);
121 itsHost
= host
.substr(at
+1);
127 bool Connection::SendPassword()
130 assert(!isCommandsListEnabled
);
131 mpd_run_password(itsConnection
, itsPassword
.c_str());
132 return !CheckForErrors();
135 void Connection::SetStatusUpdater(StatusUpdater updater
, void *data
)
137 itsUpdater
= updater
;
138 itsStatusUpdaterUserdata
= data
;
141 void Connection::SetErrorHandler(ErrorHandler handler
, void *data
)
143 itsErrorHandler
= handler
;
144 itsErrorHandlerUserdata
= data
;
147 void Connection::GoIdle()
149 if (supportsIdle
&& !isIdle
&& mpd_send_idle(itsConnection
))
153 int Connection::GoBusy()
155 if (isIdle
&& mpd_send_noidle(itsConnection
))
158 return mpd_recv_idle(itsConnection
, 1);
163 void Connection::UpdateStatus()
173 idle_mask
= GoBusy();
178 // count local elapsed time as we don't receive
179 // this from mpd while being in idle mode
180 time(&itsElapsedTimer
[1]);
181 double diff
= difftime(itsElapsedTimer
[1], itsElapsedTimer
[0]);
182 if (diff
>= 1.0 && Mpd
.GetState() == psPlay
)
184 time(&itsElapsedTimer
[0]);
186 StatusChanges changes
;
187 changes
.ElapsedTime
= 1;
189 itsUpdater(this, changes
, itsErrorHandlerUserdata
);
201 mpd_status_free(itsOldStatus
);
203 itsOldStatus
= itsCurrentStatus
;
204 itsCurrentStatus
= 0;
206 itsCurrentStatus
= mpd_run_status(itsConnection
);
208 if (!itsMaxPlaylistLength
)
209 itsMaxPlaylistLength
= GetPlaylistLength();
211 if (CheckForErrors())
214 if (itsCurrentStatus
&& itsUpdater
)
218 // sync local elapsed time counter with mpd
219 unsigned old_elapsed
= itsElapsed
;
220 itsElapsed
= mpd_status_get_elapsed_time(itsCurrentStatus
);
221 itsChanges
.ElapsedTime
= itsElapsed
!= old_elapsed
;
222 time(&itsElapsedTimer
[0]);
225 itsElapsed
= mpd_status_get_elapsed_time(itsCurrentStatus
);
229 itsChanges
.Playlist
= 1;
230 itsChanges
.SongID
= 1;
231 itsChanges
.Database
= 1;
232 itsChanges
.DBUpdating
= 1;
233 itsChanges
.Volume
= 1;
234 itsChanges
.ElapsedTime
= 1;
235 itsChanges
.Crossfade
= 1;
236 itsChanges
.Random
= 1;
237 itsChanges
.Repeat
= 1;
238 itsChanges
.Single
= 1;
239 itsChanges
.Consume
= 1;
240 itsChanges
.PlayerState
= 1;
241 itsChanges
.StatusFlags
= 1;
242 itsChanges
.Outputs
= 1;
248 itsChanges
.Playlist
= idle_mask
& MPD_IDLE_QUEUE
;
249 itsChanges
.Database
= idle_mask
& MPD_IDLE_DATABASE
;
250 itsChanges
.DBUpdating
= idle_mask
& MPD_IDLE_UPDATE
;
251 itsChanges
.Volume
= idle_mask
& MPD_IDLE_MIXER
;
252 itsChanges
.StatusFlags
= idle_mask
& (MPD_IDLE_OPTIONS
| MPD_IDLE_UPDATE
);
253 itsChanges
.Outputs
= idle_mask
& MPD_IDLE_OUTPUT
;
257 itsChanges
.Playlist
= mpd_status_get_queue_version(itsOldStatus
)
258 != mpd_status_get_queue_version(itsCurrentStatus
);
260 itsChanges
.ElapsedTime
= mpd_status_get_elapsed_time(itsOldStatus
)
261 != mpd_status_get_elapsed_time(itsCurrentStatus
);
263 itsChanges
.Database
= mpd_status_get_update_id(itsOldStatus
)
264 && !mpd_status_get_update_id(itsCurrentStatus
);
266 itsChanges
.DBUpdating
= mpd_status_get_update_id(itsOldStatus
)
267 != mpd_status_get_update_id(itsCurrentStatus
);
269 itsChanges
.Volume
= mpd_status_get_volume(itsOldStatus
)
270 != mpd_status_get_volume(itsCurrentStatus
);
272 itsChanges
.StatusFlags
= itsChanges
.Repeat
275 || itsChanges
.Consume
276 || itsChanges
.Crossfade
277 || itsChanges
.DBUpdating
;
279 // there is no way to determine if the output has changed or not
280 // from mpd status, it's possible only with idle notifications
281 itsChanges
.Outputs
= 0;
284 itsChanges
.SongID
= mpd_status_get_song_id(itsOldStatus
)
285 != mpd_status_get_song_id(itsCurrentStatus
);
287 itsChanges
.Crossfade
= mpd_status_get_crossfade(itsOldStatus
)
288 != mpd_status_get_crossfade(itsCurrentStatus
);
290 itsChanges
.Random
= mpd_status_get_random(itsOldStatus
)
291 != mpd_status_get_random(itsCurrentStatus
);
293 itsChanges
.Repeat
= mpd_status_get_repeat(itsOldStatus
)
294 != mpd_status_get_repeat(itsCurrentStatus
);
296 itsChanges
.Single
= mpd_status_get_single(itsOldStatus
)
297 != mpd_status_get_single(itsCurrentStatus
);
299 itsChanges
.Consume
= mpd_status_get_consume(itsOldStatus
)
300 != mpd_status_get_consume(itsCurrentStatus
);
302 itsChanges
.PlayerState
= mpd_status_get_state(itsOldStatus
)
303 != mpd_status_get_state(itsCurrentStatus
);
305 itsUpdater(this, itsChanges
, itsErrorHandlerUserdata
);
306 // status updater could invoke mpd commands that
307 // could fail se we need to check for errors
313 void Connection::UpdateStats()
317 assert(!isCommandsListEnabled
);
320 mpd_stats_free(itsStats
);
321 itsStats
= mpd_run_stats(itsConnection
);
325 bool Connection::UpdateDirectory(const std::string
&path
)
329 if (!isCommandsListEnabled
)
332 bool success
= mpd_run_update(itsConnection
, path
.c_str());
333 if (!supportsIdle
&& success
)
340 return mpd_send_update(itsConnection
, path
.c_str());
345 void Connection::Play()
349 if (!isCommandsListEnabled
)
352 mpd_run_play(itsConnection
);
357 mpd_send_play(itsConnection
);
361 void Connection::Play(int pos
)
365 if (!isCommandsListEnabled
)
368 mpd_run_play_pos(itsConnection
, pos
);
373 mpd_send_play_pos(itsConnection
, pos
);
377 void Connection::PlayID(int id
)
381 if (!isCommandsListEnabled
)
384 mpd_run_play_id(itsConnection
, id
);
389 mpd_send_play_id(itsConnection
, id
);
393 void Connection::Pause(bool state
)
397 if (!isCommandsListEnabled
)
400 mpd_run_pause(itsConnection
, state
);
405 mpd_send_pause(itsConnection
, state
);
409 void Connection::Toggle()
413 if (!isCommandsListEnabled
)
417 mpd_run_toggle_pause(itsConnection
);
419 mpd_run_play(itsConnection
);
425 mpd_send_toggle_pause(itsConnection
);
427 mpd_send_play(itsConnection
);
431 void Connection::Stop()
435 if (!isCommandsListEnabled
)
438 mpd_run_stop(itsConnection
);
443 mpd_send_stop(itsConnection
);
447 void Connection::Next()
451 if (!isCommandsListEnabled
)
454 mpd_run_next(itsConnection
);
459 mpd_send_next(itsConnection
);
463 void Connection::Prev()
467 if (!isCommandsListEnabled
)
470 mpd_run_previous(itsConnection
);
475 mpd_send_previous(itsConnection
);
479 void Connection::Move(unsigned from
, unsigned to
)
483 if (!isCommandsListEnabled
)
486 mpd_run_move(itsConnection
, from
, to
);
491 mpd_send_move(itsConnection
, from
, to
);
495 void Connection::Swap(unsigned from
, unsigned to
)
499 if (!isCommandsListEnabled
)
502 mpd_run_swap(itsConnection
, from
, to
);
507 mpd_send_swap(itsConnection
, from
, to
);
511 void Connection::Seek(unsigned where
)
515 if (!isCommandsListEnabled
)
518 mpd_run_seek_pos(itsConnection
, Mpd
.GetCurrentSongPos(), where
);
523 mpd_send_seek_pos(itsConnection
, Mpd
.GetCurrentSongPos(), where
);
527 void Connection::Shuffle()
531 if (!isCommandsListEnabled
)
534 mpd_run_shuffle(itsConnection
);
539 mpd_send_shuffle(itsConnection
);
543 void Connection::ClearPlaylist()
547 if (!isCommandsListEnabled
)
550 mpd_run_clear(itsConnection
);
555 mpd_send_clear(itsConnection
);
559 void Connection::ClearPlaylist(const std::string
&playlist
)
563 if (!isCommandsListEnabled
)
566 mpd_run_playlist_clear(itsConnection
, playlist
.c_str());
570 mpd_send_playlist_clear(itsConnection
, playlist
.c_str());
575 void Connection::AddToPlaylist(const std::string
&path
, const Song
&s
)
578 AddToPlaylist(path
, s
.GetFile());
581 void Connection::AddToPlaylist(const std::string
&path
, const std::string
&file
)
585 if (!isCommandsListEnabled
)
588 mpd_run_playlist_add(itsConnection
, path
.c_str(), file
.c_str());
593 mpd_send_playlist_add(itsConnection
, path
.c_str(), file
.c_str());
597 void Connection::Move(const std::string
&path
, int from
, int to
)
601 if (!isCommandsListEnabled
)
605 mpd_send_playlist_move(itsConnection
, path
.c_str(), from
, to
);
606 if (!isCommandsListEnabled
)
607 mpd_response_finish(itsConnection
);
610 bool Connection::Rename(const std::string
&from
, const std::string
&to
)
614 if (!isCommandsListEnabled
)
617 return mpd_run_rename(itsConnection
, from
.c_str(), to
.c_str());
622 return mpd_send_rename(itsConnection
, from
.c_str(), to
.c_str());
626 void Connection::GetPlaylistChanges(unsigned version
, SongList
&v
)
630 assert(!isCommandsListEnabled
);
632 v
.reserve(GetPlaylistLength());
634 mpd_send_queue_changes_meta(itsConnection
, version
);
635 while (mpd_song
*s
= mpd_recv_song(itsConnection
))
636 v
.push_back(new Song(s
, 1));
637 mpd_response_finish(itsConnection
);
641 Song
Connection::GetSong(const std::string
&path
)
645 assert(!isCommandsListEnabled
);
647 mpd_send_list_all_meta(itsConnection
, path
.c_str());
648 mpd_song
*s
= mpd_recv_song(itsConnection
);
649 mpd_response_finish(itsConnection
);
654 int Connection::GetCurrentSongPos() const
656 return itsCurrentStatus
&& isPlaying() ? mpd_status_get_song_pos(itsCurrentStatus
) : -1;
659 Song
Connection::GetCurrentSong()
661 assert(!isCommandsListEnabled
);
663 Song result
= Song(itsConnection
&& isPlaying() ? mpd_run_current_song(itsConnection
) : 0);
668 void Connection::GetPlaylistContent(const std::string
&path
, SongList
&v
)
672 assert(!isCommandsListEnabled
);
674 mpd_send_list_playlist_meta(itsConnection
, path
.c_str());
675 while (mpd_song
*s
= mpd_recv_song(itsConnection
))
676 v
.push_back(new Song(s
));
677 mpd_response_finish(itsConnection
);
681 void Connection::SetRepeat(bool mode
)
685 if (!isCommandsListEnabled
)
688 mpd_run_repeat(itsConnection
, mode
);
693 mpd_send_repeat(itsConnection
, mode
);
697 void Connection::SetRandom(bool mode
)
701 if (!isCommandsListEnabled
)
704 mpd_run_random(itsConnection
, mode
);
709 mpd_send_random(itsConnection
, mode
);
713 void Connection::SetSingle(bool mode
)
717 if (!isCommandsListEnabled
)
720 mpd_run_single(itsConnection
, mode
);
725 mpd_send_single(itsConnection
, mode
);
729 void Connection::SetConsume(bool mode
)
733 if (!isCommandsListEnabled
)
736 mpd_run_consume(itsConnection
, mode
);
741 mpd_send_consume(itsConnection
, mode
);
745 void Connection::SetVolume(unsigned vol
)
747 if (!itsConnection
|| vol
> 100)
749 assert(!isCommandsListEnabled
);
751 if (mpd_run_set_volume(itsConnection
, vol
) && !supportsIdle
)
755 std::string
Connection::GetReplayGainMode()
759 assert(!isCommandsListEnabled
);
761 if (!mpd_send_command(itsConnection
, "replay_gain_status", NULL
))
764 if (mpd_pair
*pair
= mpd_recv_pair_named(itsConnection
, "replay_gain_mode"))
766 result
= pair
->value
;
768 result
[0] = toupper(result
[0]);
769 mpd_return_pair(itsConnection
, pair
);
771 mpd_response_finish(itsConnection
);
775 void Connection::SetReplayGainMode(ReplayGainMode mode
)
792 FatalError("undefined value of ReplayGainMode!");
794 if (!isCommandsListEnabled
)
798 if (!mpd_send_command(itsConnection
, "replay_gain_mode", rg_mode
, NULL
))
800 if (!isCommandsListEnabled
)
801 mpd_response_finish(itsConnection
);
804 void Connection::SetCrossfade(unsigned crossfade
)
808 if (!isCommandsListEnabled
)
811 mpd_run_crossfade(itsConnection
, crossfade
);
816 mpd_send_crossfade(itsConnection
, crossfade
);
820 int Connection::AddSong(const std::string
&path
, int pos
)
825 if (GetPlaylistLength() < itsMaxPlaylistLength
)
827 if (!isCommandsListEnabled
)
832 mpd_send_add_id(itsConnection
, path
.c_str());
834 mpd_send_add_id_to(itsConnection
, path
.c_str(), pos
);
835 if (!isCommandsListEnabled
)
837 id
= mpd_recv_song_id(itsConnection
);
838 mpd_response_finish(itsConnection
);
843 else if (itsErrorHandler
)
844 itsErrorHandler(this, MPD_SERVER_ERROR_PLAYLIST_MAX
, Message::FullPlaylist
, itsErrorHandlerUserdata
);
848 int Connection::AddSong(const Song
&s
, int pos
)
850 return !s
.Empty() ? (AddSong((!s
.isFromDB() ? "file://" : "") + (s
.Localized() ? locale_to_utf_cpy(s
.GetFile()) : s
.GetFile()), pos
)) : -1;
853 void Connection::Add(const std::string
&path
)
857 if (!isCommandsListEnabled
)
860 mpd_run_add(itsConnection
, path
.c_str());
865 mpd_send_add(itsConnection
, path
.c_str());
869 bool Connection::AddRandomSongs(size_t number
)
871 if (!itsConnection
&& !number
)
873 assert(!isCommandsListEnabled
);
878 mpd_send_list_all(itsConnection
, "/");
879 while (mpd_pair
*item
= mpd_recv_pair_named(itsConnection
, "file"))
881 files
.push_back(item
->value
);
882 mpd_return_pair(itsConnection
, item
);
884 mpd_response_finish(itsConnection
);
886 if (number
> files
.size())
889 itsErrorHandler(this, 0, "Requested number of random songs is bigger than size of your library!", itsErrorHandlerUserdata
);
895 std::random_shuffle(files
.begin(), files
.end());
897 TagList::const_iterator it
= files
.begin()+rand()%(files
.size()-number
);
898 for (size_t i
= 0; i
< number
&& it
!= files
.end(); ++i
)
900 CommitCommandsList();
905 bool Connection::Delete(unsigned pos
)
909 if (!isCommandsListEnabled
)
913 bool result
= mpd_send_delete(itsConnection
, pos
);
914 if (!isCommandsListEnabled
)
915 result
= mpd_response_finish(itsConnection
);
919 bool Connection::DeleteID(unsigned id
)
923 if (!isCommandsListEnabled
)
927 bool result
= mpd_send_delete_id(itsConnection
, id
);
928 if (!isCommandsListEnabled
)
929 result
= mpd_response_finish(itsConnection
);
933 bool Connection::Delete(const std::string
&playlist
, unsigned pos
)
937 if (!isCommandsListEnabled
)
940 return mpd_run_playlist_delete(itsConnection
, playlist
.c_str(), pos
);
945 return mpd_send_playlist_delete(itsConnection
, playlist
.c_str(), pos
);
949 void Connection::StartCommandsList()
953 assert(!isCommandsListEnabled
);
955 mpd_command_list_begin(itsConnection
, 1);
956 isCommandsListEnabled
= 1;
959 bool Connection::CommitCommandsList()
963 assert(isCommandsListEnabled
);
965 mpd_command_list_end(itsConnection
);
966 mpd_response_finish(itsConnection
);
967 if (GetPlaylistLength() == itsMaxPlaylistLength
&& itsErrorHandler
)
968 itsErrorHandler(this, MPD_SERVER_ERROR_PLAYLIST_MAX
, Message::FullPlaylist
, itsErrorHandlerUserdata
);
969 isCommandsListEnabled
= 0;
970 bool result
= !CheckForErrors();
975 bool Connection::DeletePlaylist(const std::string
&name
)
979 if (!isCommandsListEnabled
)
982 return mpd_run_rm(itsConnection
, name
.c_str());
987 return mpd_send_rm(itsConnection
, name
.c_str());
991 bool Connection::SavePlaylist(const std::string
&name
)
995 assert(!isCommandsListEnabled
);
997 mpd_send_save(itsConnection
, name
.c_str());
998 mpd_response_finish(itsConnection
);
999 return !(mpd_connection_get_error(itsConnection
) == MPD_ERROR_SERVER
1000 && mpd_connection_get_server_error(itsConnection
) == MPD_SERVER_ERROR_EXIST
);
1003 void Connection::GetPlaylists(TagList
&v
)
1008 GetDirectory("/", list
);
1009 for (ItemList::const_iterator it
= list
.begin(); it
!= list
.end(); ++it
)
1010 if (it
->type
== itPlaylist
)
1011 v
.push_back(it
->name
);
1015 void Connection::GetList(TagList
&v
, mpd_tag_type type
)
1019 assert(!isCommandsListEnabled
);
1021 mpd_search_db_tags(itsConnection
, type
);
1022 mpd_search_commit(itsConnection
);
1023 while (mpd_pair
*item
= mpd_recv_pair_tag(itsConnection
, type
))
1025 if (item
->value
[0] != 0) // do not push empty item
1026 v
.push_back(item
->value
);
1027 mpd_return_pair(itsConnection
, item
);
1029 mpd_response_finish(itsConnection
);
1033 void Connection::GetAlbums(const std::string
&artist
, TagList
&v
)
1037 assert(!isCommandsListEnabled
);
1039 mpd_search_db_tags(itsConnection
, MPD_TAG_ALBUM
);
1040 if (!artist
.empty())
1041 mpd_search_add_tag_constraint(itsConnection
, MPD_OPERATOR_DEFAULT
, MPD_TAG_ARTIST
, artist
.c_str());
1042 mpd_search_commit(itsConnection
);
1043 while (mpd_pair
*item
= mpd_recv_pair_tag(itsConnection
, MPD_TAG_ALBUM
))
1045 if (item
->value
[0] != 0) // do not push empty item
1046 v
.push_back(item
->value
);
1047 mpd_return_pair(itsConnection
, item
);
1049 mpd_response_finish(itsConnection
);
1053 void Connection::StartSearch(bool exact_match
)
1056 mpd_search_db_songs(itsConnection
, exact_match
);
1059 void Connection::StartFieldSearch(mpd_tag_type item
)
1063 itsSearchedField
= item
;
1064 mpd_search_db_tags(itsConnection
, item
);
1068 void Connection::AddSearch(mpd_tag_type item
, const std::string
&str
)
1070 // mpd version < 0.14.* doesn't support empty search constraints
1071 if (Version() < 14 && str
.empty())
1074 mpd_search_add_tag_constraint(itsConnection
, MPD_OPERATOR_DEFAULT
, item
, str
.c_str());
1077 void Connection::CommitSearch(SongList
&v
)
1081 assert(!isCommandsListEnabled
);
1083 mpd_search_commit(itsConnection
);
1084 while (mpd_song
*s
= mpd_recv_song(itsConnection
))
1085 v
.push_back(new Song(s
));
1086 mpd_response_finish(itsConnection
);
1090 void Connection::CommitSearch(TagList
&v
)
1094 assert(!isCommandsListEnabled
);
1096 mpd_search_commit(itsConnection
);
1097 while (mpd_pair
*tag
= mpd_recv_pair_tag(itsConnection
, itsSearchedField
))
1099 if (tag
->value
[0] != 0) // do not push empty item
1100 v
.push_back(tag
->value
);
1101 mpd_return_pair(itsConnection
, tag
);
1103 mpd_response_finish(itsConnection
);
1107 void Connection::GetDirectory(const std::string
&path
, ItemList
&v
)
1111 assert(!isCommandsListEnabled
);
1113 mpd_send_list_meta(itsConnection
, path
.c_str());
1114 while (mpd_entity
*item
= mpd_recv_entity(itsConnection
))
1117 switch (mpd_entity_get_type(item
))
1119 case MPD_ENTITY_TYPE_DIRECTORY
:
1120 it
.name
= mpd_directory_get_path(mpd_entity_get_directory(item
));
1121 it
.type
= itDirectory
;
1123 case MPD_ENTITY_TYPE_SONG
:
1124 it
.song
= new Song(mpd_song_dup(mpd_entity_get_song(item
)));
1127 case MPD_ENTITY_TYPE_PLAYLIST
:
1128 it
.name
= mpd_playlist_get_path(mpd_entity_get_playlist(item
));
1129 it
.type
= itPlaylist
;
1137 mpd_entity_free(item
);
1139 mpd_response_finish(itsConnection
);
1143 void Connection::GetDirectoryRecursive(const std::string
&path
, SongList
&v
)
1147 assert(!isCommandsListEnabled
);
1149 mpd_send_list_all_meta(itsConnection
, path
.c_str());
1150 while (mpd_song
*s
= mpd_recv_song(itsConnection
))
1151 v
.push_back(new Song(s
));
1152 mpd_response_finish(itsConnection
);
1156 void Connection::GetSongs(const std::string
&path
, SongList
&v
)
1160 assert(!isCommandsListEnabled
);
1162 mpd_send_list_meta(itsConnection
, path
.c_str());
1163 while (mpd_song
*s
= mpd_recv_song(itsConnection
))
1164 v
.push_back(new Song(s
));
1165 mpd_response_finish(itsConnection
);
1169 void Connection::GetDirectories(const std::string
&path
, TagList
&v
)
1173 assert(!isCommandsListEnabled
);
1175 mpd_send_list_meta(itsConnection
, path
.c_str());
1176 while (mpd_directory
*dir
= mpd_recv_directory(itsConnection
))
1178 v
.push_back(mpd_directory_get_path(dir
));
1179 mpd_directory_free(dir
);
1181 mpd_response_finish(itsConnection
);
1185 void Connection::GetOutputs(OutputList
&v
)
1189 assert(!isCommandsListEnabled
);
1191 mpd_send_outputs(itsConnection
);
1192 while (mpd_output
*output
= mpd_recv_output(itsConnection
))
1194 v
.push_back(std::make_pair(mpd_output_get_name(output
), mpd_output_get_enabled(output
)));
1195 mpd_output_free(output
);
1197 mpd_response_finish(itsConnection
);
1201 bool Connection::EnableOutput(int id
)
1205 if (!isCommandsListEnabled
)
1208 return mpd_run_enable_output(itsConnection
, id
);
1213 return mpd_send_enable_output(itsConnection
, id
);
1217 bool Connection::DisableOutput(int id
)
1221 if (!isCommandsListEnabled
)
1224 return mpd_run_disable_output(itsConnection
, id
);
1229 return mpd_send_disable_output(itsConnection
, id
);
1233 void Connection::GetURLHandlers(TagList
&v
)
1237 assert(!isCommandsListEnabled
);
1239 mpd_send_list_url_schemes(itsConnection
);
1240 while (mpd_pair
*handler
= mpd_recv_pair_named(itsConnection
, "handler"))
1242 v
.push_back(handler
->value
);
1243 mpd_return_pair(itsConnection
, handler
);
1245 mpd_response_finish(itsConnection
);
1249 void Connection::GetTagTypes(TagList
&v
)
1253 assert(!isCommandsListEnabled
);
1255 mpd_send_list_tag_types(itsConnection
);
1256 while (mpd_pair
*tag_type
= mpd_recv_pair_named(itsConnection
, "tagtype"))
1258 v
.push_back(tag_type
->value
);
1259 mpd_return_pair(itsConnection
, tag_type
);
1261 mpd_response_finish(itsConnection
);
1265 int Connection::CheckForErrors()
1268 if ((error_code
= mpd_connection_get_error(itsConnection
)) != MPD_ERROR_SUCCESS
)
1270 itsErrorMessage
= mpd_connection_get_error_message(itsConnection
);
1271 if (error_code
== MPD_ERROR_SERVER
)
1273 // this is to avoid setting too small max size as we check it before fetching current status
1274 // setting real max playlist length is in UpdateStatus()
1275 error_code
= mpd_connection_get_server_error(itsConnection
);
1276 if (error_code
== MPD_SERVER_ERROR_PLAYLIST_MAX
&& itsMaxPlaylistLength
== size_t(-1))
1277 itsMaxPlaylistLength
= 0;
1279 if (!mpd_connection_clear_error(itsConnection
))
1281 if (itsErrorHandler
)
1282 itsErrorHandler(this, error_code
, itsErrorMessage
.c_str(), itsErrorHandlerUserdata
);
1287 void MPD::FreeSongList(SongList
&l
)
1289 for (SongList::iterator i
= l
.begin(); i
!= l
.end(); ++i
)
1294 void MPD::FreeItemList(ItemList
&l
)
1296 for (ItemList::iterator i
= l
.begin(); i
!= l
.end(); ++i
)