Compiler.h: move to util/
[ncmpc-debian.git] / src / save_playlist.cxx
1 /* ncmpc (Ncurses MPD Client)
2  * (c) 2004-2018 The Music Player Daemon Project
3  * Project homepage: http://musicpd.org
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 "save_playlist.hxx"
21 #include "db_completion.hxx"
22 #include "screen_status.hxx"
23 #include "config.h"
24 #include "i18n.h"
25 #include "charset.hxx"
26 #include "mpdclient.hxx"
27 #include "wreadln.hxx"
28 #include "Completion.hxx"
29 #include "screen_utils.hxx"
30 #include "util/Compiler.h"
31
32 #include <mpd/client.h>
33
34 #include <string.h>
35
36 #ifndef NCMPC_MINI
37
38 class PlaylistNameCompletion final : public Completion {
39         struct mpdclient &c;
40
41 public:
42         explicit PlaylistNameCompletion(struct mpdclient &_c)
43                 :c(_c) {}
44
45 protected:
46         /* virtual methods from class Completion */
47         void Pre(const char *value) override;
48         void Post(const char *value, Range range) override;
49 };
50
51 void
52 PlaylistNameCompletion::Pre(gcc_unused const char *value)
53 {
54         if (empty()) {
55                 /* create completion list */
56                 gcmp_list_from_path(&c, "", *this, GCMP_TYPE_PLAYLIST);
57         }
58 }
59
60 void
61 PlaylistNameCompletion::Post(gcc_unused const char *value, Range range)
62 {
63         if (range.begin() != range.end() &&
64             std::next(range.begin()) != range.end())
65                 screen_display_completion_list(range);
66 }
67
68 #endif
69
70 int
71 playlist_save(struct mpdclient *c, char *name, char *defaultname)
72 {
73         std::string filename;
74
75         if (name == nullptr) {
76 #ifdef NCMPC_MINI
77                 Completion *completion = nullptr;
78 #else
79                 /* initialize completion support */
80                 PlaylistNameCompletion _completion(*c);
81                 auto *completion = &_completion;
82 #endif
83
84                 /* query the user for a filename */
85                 filename = screen_readln(_("Save queue as"),
86                                          defaultname,
87                                          nullptr,
88                                          completion);
89                 if (filename.empty())
90                         return -1;
91         } else
92                 filename = name;
93
94         /* send save command to mpd */
95
96         auto *connection = c->GetConnection();
97         if (connection == nullptr)
98                 return -1;
99
100         const LocaleToUtf8 filename_utf8(filename.c_str());
101         if (!mpd_run_save(connection, filename_utf8.c_str())) {
102                 if (mpd_connection_get_error(connection) == MPD_ERROR_SERVER &&
103                     mpd_connection_get_server_error(connection) == MPD_SERVER_ERROR_EXIST &&
104                     mpd_connection_clear_error(connection)) {
105                         char prompt[256];
106                         snprintf(prompt, sizeof(prompt),
107                                  _("Replace %s?"), filename.c_str());
108                         bool replace = screen_get_yesno(prompt, false);
109                         if (!replace) {
110                                 screen_status_message(_("Aborted"));
111                                 return -1;
112                         }
113
114                         if (!mpd_run_rm(connection, filename_utf8.c_str()) ||
115                             !mpd_run_save(connection, filename_utf8.c_str())) {
116                                 c->HandleError();
117                                 return -1;
118                         }
119                 } else {
120                         c->HandleError();
121                         return -1;
122                 }
123         }
124
125         c->events |= MPD_IDLE_STORED_PLAYLIST;
126
127         /* success */
128         screen_status_printf(_("Saved %s"), filename.c_str());
129         return 0;
130 }