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 #include "tag_editor.h"
39 std::cout
<< "Cannot connect to mpd: " << Mpd
.GetErrorMessage() << std::endl
;
45 void ParseArgv(int argc
, char **argv
)
48 std::string now_playing_format
= "{{(%l) }{{%a - }%t}}|{%f}}";
50 for (int i
= 1; i
< argc
; ++i
)
52 if (!strcmp(argv
[i
], "-h") || !strcmp(argv
[i
], "--host"))
56 Mpd
.SetHostname(argv
[i
]);
59 if (!strcmp(argv
[i
], "-p") || !strcmp(argv
[i
], "--port"))
63 Mpd
.SetPort(atoi(argv
[i
]));
66 else if (!strcmp(argv
[i
], "-v") || !strcmp(argv
[i
], "--version"))
68 std::cout
<< "ncmpcpp version: " << VERSION
<< "\n\n"
69 << "optional screens compiled-in:\n"
72 << " - tiny tag editor\n"
74 # ifdef HAVE_CURL_CURL_H
77 # ifdef ENABLE_OUTPUTS
80 # ifdef ENABLE_VISUALIZER
86 << "\nencoding detection: "
87 # ifdef HAVE_LANGINFO_H
91 # endif // HAVE_LANGINFO_H
92 << "\nbuilt with support for:"
93 # ifdef HAVE_CURL_CURL_H
107 # ifdef HAVE_TAGLIB_H
110 # ifdef HAVE_PTHREAD_H
119 else if (!strcmp(argv
[i
], "-?") || !strcmp(argv
[i
], "--help"))
122 << "Usage: ncmpcpp [OPTION]...\n"
123 << " -h, --host connect to server at host [localhost]\n"
124 << " -p, --port connect to server at port [6600]\n"
125 << " -?, --help show this help message\n"
126 << " -v, --version display version information\n"
127 << " --now-playing display now playing song [" << now_playing_format
<< "]\n"
129 << " play start playing\n"
130 << " pause pause the currently playing song\n"
131 << " toggle toggle play/pause mode\n"
132 << " stop stop playing\n"
133 << " next play the next song\n"
134 << " prev play the previous song\n"
135 << " volume [+-]<num> adjusts volume by [+-]<num>\n"
143 if (!strcmp(argv
[i
], "--now-playing"))
146 if (!Mpd
.GetErrorMessage().empty())
148 std::cout
<< "Error: " << Mpd
.GetErrorMessage() << std::endl
;
155 // apply additional pair of braces
156 now_playing_format
= "{";
157 now_playing_format
+= argv
[i
];
158 now_playing_format
+= "}";
159 Replace(now_playing_format
, "\\n", "\n");
160 Replace(now_playing_format
, "\\t", "\t");
161 MPD::Song::ValidateFormat("now-playing format", now_playing_format
);
163 std::cout
<< utf_to_locale_cpy(Mpd
.GetCurrentSong().toString(now_playing_format
)) << "\n";
167 else if (!strcmp(argv
[i
], "play"))
172 else if (!strcmp(argv
[i
], "pause"))
177 else if (!strcmp(argv
[i
], "toggle"))
180 if (!Mpd
.GetErrorMessage().empty())
182 std::cout
<< "Error: " << Mpd
.GetErrorMessage() << std::endl
;
188 else if (!strcmp(argv
[i
], "stop"))
193 else if (!strcmp(argv
[i
], "next"))
198 else if (!strcmp(argv
[i
], "prev"))
203 else if (!strcmp(argv
[i
], "volume"))
207 if (!Mpd
.GetErrorMessage().empty())
209 std::cout
<< "Error: " << Mpd
.GetErrorMessage() << std::endl
;
213 Mpd
.SetVolume(Mpd
.GetVolume()+atoi(argv
[i
]));
218 std::cout
<< "ncmpcpp: invalid option: " << argv
[i
] << std::endl
;
221 if (!Mpd
.GetErrorMessage().empty())
223 std::cout
<< "Error: " << Mpd
.GetErrorMessage() << std::endl
;
231 bool CaseInsensitiveSorting::operator()(const Item
&a
, const Item
&b
)
233 if (a
.type
== b
.type
)
238 return cmp(ExtractTopDirectory(a
.name
), ExtractTopDirectory(b
.name
)) < 0;
240 return cmp(a
.name
, b
.name
) < 0;
242 return Config
.browser_sort_by_mtime
243 ? a
.song
->GetMTime() > b
.song
->GetMTime()
244 : operator()(a
.song
, b
.song
);
245 default: // there's no other type, just silence compiler.
250 return a
.type
< b
.type
;
253 std::string
Timestamp(time_t t
)
257 result
[strftime(result
, 31, "%x %X", localtime_r(&t
, &info
))] = 0;
261 void UpdateSongList(Menu
<Song
> *menu
)
264 for (size_t i
= 0; i
< menu
->Size(); ++i
)
266 for (size_t j
= 0; j
< myPlaylist
->Items
->Size(); ++j
)
268 if (myPlaylist
->Items
->at(j
).GetHash() == menu
->at(i
).GetHash())
281 std::string
FindSharedDir(Menu
<Song
> *menu
)
284 for (size_t i
= 0; i
< menu
->Size(); ++i
)
285 list
.push_back(&(*menu
)[i
]);
286 return FindSharedDir(list
);
289 std::string
FindSharedDir(const SongList
&v
)
291 if (v
.empty()) // this should never happen, but in case...
292 FatalError("empty SongList passed to FindSharedDir(const SongList &)!");
294 std::string first
= v
.front()->GetDirectory();
295 for (SongList::const_iterator it
= ++v
.begin(); it
!= v
.end(); ++it
)
298 std::string dir
= (*it
)->GetDirectory();
299 size_t length
= std::min(first
.length(), dir
.length());
300 while (!first
.compare(j
, 1, dir
, j
, 1) && j
< length
&& j
< i
)
304 return i
? first
.substr(0, i
) : "/";
306 #endif // HAVE_TAGLIB_H
308 std::string
FindSharedDir(const std::string
&one
, const std::string
&two
)
313 while (!one
.compare(i
, 1, two
, i
, 1))
315 i
= one
.rfind("/", i
);
316 return i
!= std::string::npos
? one
.substr(0, i
) : "/";
319 std::string
GetLineValue(std::string
&line
, char a
, char b
, bool once
)
321 int pos
[2] = { -1, -1 };
323 for (i
= line
.find(a
); i
!= std::string::npos
&& pos
[1] < 0; i
= line
.find(b
, i
))
325 if (i
&& line
[i
-1] == '\\')
332 pos
[pos
[0] >= 0] = i
++;
335 std::string result
= pos
[0] >= 0 && pos
[1] >= 0 ? line
.substr(pos
[0], pos
[1]-pos
[0]) : "";
336 Replace(result
, "\\\"", "\"");
340 std::string
ExtractTopDirectory(const std::string
&s
)
342 size_t slash
= s
.rfind("/");
343 return slash
!= std::string::npos
? s
.substr(++slash
) : s
;
346 std::basic_string
<my_char_t
> Scroller(const std::basic_string
<my_char_t
> &str
, size_t &pos
, size_t width
)
348 std::basic_string
<my_char_t
> s(str
);
349 if (!Config
.header_text_scrolling
)
351 std::basic_string
<my_char_t
> result
;
352 size_t len
= Window::Length(s
);
358 std::basic_string
<my_char_t
>::const_iterator b
= s
.begin(), e
= s
.end();
359 for (std::basic_string
<my_char_t
>::const_iterator it
= b
+pos
; it
< e
&& len
< width
; ++it
)
361 if ((len
+= wcwidth(*it
)) > width
)
365 if (++pos
>= s
.length())
367 for (; len
< width
; ++b
)
369 if ((len
+= wcwidth(*b
)) > width
)
379 #ifdef HAVE_CURL_CURL_H
380 size_t write_data(char *buffer
, size_t size
, size_t nmemb
, void *data
)
382 size_t result
= size
*nmemb
;
383 static_cast<std::string
*>(data
)->append(buffer
, result
);
386 #endif // HAVE_CURL_CURL_H