more cleanup and grouping functions logically together

This commit is contained in:
Andrzej Rybczak
2012-08-29 14:34:39 +02:00
parent b1c301dc1c
commit b06e620913
28 changed files with 486 additions and 512 deletions

View File

@@ -3,11 +3,11 @@ ncmpcpp_SOURCES = \
utility/comparators.cpp \ utility/comparators.cpp \
utility/html.cpp \ utility/html.cpp \
utility/string.cpp \ utility/string.cpp \
utility/type_conversions.cpp \
actions.cpp \ actions.cpp \
browser.cpp \ browser.cpp \
charset.cpp \ charset.cpp \
clock.cpp \ clock.cpp \
conv.cpp \
curl_handle.cpp \ curl_handle.cpp \
display.cpp \ display.cpp \
error.cpp \ error.cpp \
@@ -49,10 +49,11 @@ noinst_HEADERS = \
utility/comparators.h \ utility/comparators.h \
utility/html.h \ utility/html.h \
utility/string.h \ utility/string.h \
utility/numeric_conversions.h \
utility/type_conversions.h \
browser.h \ browser.h \
charset.h \ charset.h \
clock.h \ clock.h \
conv.h \
curl_handle.h \ curl_handle.h \
display.h \ display.h \
error.h \ error.h \
@@ -68,7 +69,6 @@ noinst_HEADERS = \
menu.h \ menu.h \
mpdpp.h \ mpdpp.h \
mutable_song.h \ mutable_song.h \
numeric_conversions.h \
outputs.h \ outputs.h \
playlist_editor.h \ playlist_editor.h \
screen.h \ screen.h \

View File

@@ -20,6 +20,7 @@
#include <cassert> #include <cassert>
#include <cerrno> #include <cerrno>
#include <cstring>
#include <iostream> #include <iostream>
#include "actions.h" #include "actions.h"
@@ -44,6 +45,7 @@
#include "song_info.h" #include "song_info.h"
#include "outputs.h" #include "outputs.h"
#include "utility/string.h" #include "utility/string.h"
#include "utility/type_conversions.h"
#include "tag_editor.h" #include "tag_editor.h"
#include "tiny_tag_editor.h" #include "tiny_tag_editor.h"
#include "visualizer.h" #include "visualizer.h"
@@ -786,7 +788,7 @@ void Delete::Run()
if (Mpd.DeletePlaylist(locale_to_utf_cpy(name))) if (Mpd.DeletePlaylist(locale_to_utf_cpy(name)))
{ {
const char msg[] = "Playlist \"%s\" deleted"; const char msg[] = "Playlist \"%s\" deleted";
ShowMessage(msg, Shorten(TO_WSTRING(name), COLS-static_strlen(msg)).c_str()); ShowMessage(msg, Shorten(TO_WSTRING(name), COLS-const_strlen(msg)).c_str());
if (myBrowser->Main() && !myBrowser->isLocal() && myBrowser->CurrentDir() == "/") if (myBrowser->Main() && !myBrowser->isLocal() && myBrowser->CurrentDir() == "/")
myBrowser->GetDirectory("/"); myBrowser->GetDirectory("/");
} }
@@ -844,12 +846,12 @@ void Delete::Run()
if (myBrowser->DeleteItem(it)) if (myBrowser->DeleteItem(it))
{ {
const char msg[] = "\"%s\" deleted"; const char msg[] = "\"%s\" deleted";
ShowMessage(msg, Shorten(TO_WSTRING(name), COLS-static_strlen(msg)).c_str()); ShowMessage(msg, Shorten(TO_WSTRING(name), COLS-const_strlen(msg)).c_str());
} }
else else
{ {
const char msg[] = "Couldn't delete \"%s\": %s"; const char msg[] = "Couldn't delete \"%s\": %s";
ShowMessage(msg, Shorten(TO_WSTRING(name), COLS-static_strlen(msg)-25).c_str(), strerror(errno)); ShowMessage(msg, Shorten(TO_WSTRING(name), COLS-const_strlen(msg)-25).c_str(), strerror(errno));
success = 0; success = 0;
break; break;
} }
@@ -1109,7 +1111,7 @@ void Add::Run()
else else
{ {
const char lastfm_url[] = "lastfm://"; const char lastfm_url[] = "lastfm://";
if (path.compare(0, static_strlen(lastfm_url), lastfm_url) == 0 if (path.compare(0, const_strlen(lastfm_url), lastfm_url) == 0
|| path.find(".asx", path.length()-4) != std::string::npos || path.find(".asx", path.length()-4) != std::string::npos
|| path.find(".cue", path.length()-4) != std::string::npos || path.find(".cue", path.length()-4) != std::string::npos
|| path.find(".m3u", path.length()-4) != std::string::npos || path.find(".m3u", path.length()-4) != std::string::npos
@@ -1372,7 +1374,7 @@ void SetCrossfade::Run()
Statusbar() << "Set crossfade to: "; Statusbar() << "Set crossfade to: ";
std::string crossfade = wFooter->GetString(3); std::string crossfade = wFooter->GetString(3);
UnlockStatusbar(); UnlockStatusbar();
int cf = StrToInt(crossfade); int cf = stringToInt(crossfade);
if (cf > 0) if (cf > 0)
{ {
Config.crossfade_time = cf; Config.crossfade_time = cf;
@@ -1419,7 +1421,7 @@ void EditLibraryTag::Run()
if (!isMPDMusicDirSet()) if (!isMPDMusicDirSet())
return; return;
LockStatusbar(); LockStatusbar();
Statusbar() << fmtBold << IntoStr(Config.media_lib_primary_tag) << fmtBoldEnd << ": "; Statusbar() << fmtBold << tagTypeToString(Config.media_lib_primary_tag) << fmtBoldEnd << ": ";
std::string new_tag = wFooter->GetString(myLibrary->Artists->Current()); std::string new_tag = wFooter->GetString(myLibrary->Artists->Current());
UnlockStatusbar(); UnlockStatusbar();
if (!new_tag.empty() && new_tag != myLibrary->Artists->Current()) if (!new_tag.empty() && new_tag != myLibrary->Artists->Current())
@@ -1427,7 +1429,7 @@ void EditLibraryTag::Run()
ShowMessage("Updating tags..."); ShowMessage("Updating tags...");
Mpd.StartSearch(1); Mpd.StartSearch(1);
Mpd.AddSearch(Config.media_lib_primary_tag, locale_to_utf_cpy(myLibrary->Artists->Current())); Mpd.AddSearch(Config.media_lib_primary_tag, locale_to_utf_cpy(myLibrary->Artists->Current()));
MPD::MutableSong::SetFunction set = IntoSetFunction(Config.media_lib_primary_tag); MPD::MutableSong::SetFunction set = tagTypeToSetFunction(Config.media_lib_primary_tag);
assert(set); assert(set);
bool success = true; bool success = true;
std::string dir_to_update; std::string dir_to_update;
@@ -1441,7 +1443,7 @@ void EditLibraryTag::Run()
if (!TagEditor::WriteTags(es)) if (!TagEditor::WriteTags(es))
{ {
const char msg[] = "Error while updating tags in \"%s\""; const char msg[] = "Error while updating tags in \"%s\"";
ShowMessage(msg, Shorten(TO_WSTRING(es.getURI()), COLS-static_strlen(msg)).c_str()); ShowMessage(msg, Shorten(TO_WSTRING(es.getURI()), COLS-const_strlen(msg)).c_str());
success = false; success = false;
} }
if (dir_to_update.empty()) if (dir_to_update.empty())
@@ -1491,7 +1493,7 @@ void EditLibraryAlbum::Run()
if (f.isNull()) if (f.isNull())
{ {
const char msg[] = "Error while opening file \"%s\""; const char msg[] = "Error while opening file \"%s\"";
ShowMessage(msg, Shorten(TO_WSTRING((*myLibrary->Songs)[i].getURI()), COLS-static_strlen(msg)).c_str()); ShowMessage(msg, Shorten(TO_WSTRING((*myLibrary->Songs)[i].getURI()), COLS-const_strlen(msg)).c_str());
success = 0; success = 0;
break; break;
} }
@@ -1499,7 +1501,7 @@ void EditLibraryAlbum::Run()
if (!f.save()) if (!f.save())
{ {
const char msg[] = "Error while writing tags in \"%s\""; const char msg[] = "Error while writing tags in \"%s\"";
ShowMessage(msg, Shorten(TO_WSTRING((*myLibrary->Songs)[i].getURI()), COLS-static_strlen(msg)).c_str()); ShowMessage(msg, Shorten(TO_WSTRING((*myLibrary->Songs)[i].getURI()), COLS-const_strlen(msg)).c_str());
success = 0; success = 0;
break; break;
} }
@@ -1553,7 +1555,7 @@ void EditDirectoryName::Run()
if (rename_result == 0) if (rename_result == 0)
{ {
const char msg[] = "Directory renamed to \"%s\""; const char msg[] = "Directory renamed to \"%s\"";
ShowMessage(msg, Shorten(TO_WSTRING(new_dir), COLS-static_strlen(msg)).c_str()); ShowMessage(msg, Shorten(TO_WSTRING(new_dir), COLS-const_strlen(msg)).c_str());
if (!myBrowser->isLocal()) if (!myBrowser->isLocal())
Mpd.UpdateDirectory(locale_to_utf_cpy(getSharedDirectory(old_dir, new_dir))); Mpd.UpdateDirectory(locale_to_utf_cpy(getSharedDirectory(old_dir, new_dir)));
myBrowser->GetDirectory(myBrowser->CurrentDir()); myBrowser->GetDirectory(myBrowser->CurrentDir());
@@ -1561,7 +1563,7 @@ void EditDirectoryName::Run()
else else
{ {
const char msg[] = "Couldn't rename \"%s\": %s"; const char msg[] = "Couldn't rename \"%s\": %s";
ShowMessage(msg, Shorten(TO_WSTRING(old_dir), COLS-static_strlen(msg)-25).c_str(), strerror(errno)); ShowMessage(msg, Shorten(TO_WSTRING(old_dir), COLS-const_strlen(msg)-25).c_str(), strerror(errno));
} }
} }
} }
@@ -1580,13 +1582,13 @@ void EditDirectoryName::Run()
if (rename(full_old_dir.c_str(), full_new_dir.c_str()) == 0) if (rename(full_old_dir.c_str(), full_new_dir.c_str()) == 0)
{ {
const char msg[] = "Directory renamed to \"%s\""; const char msg[] = "Directory renamed to \"%s\"";
ShowMessage(msg, Shorten(TO_WSTRING(new_dir), COLS-static_strlen(msg)).c_str()); ShowMessage(msg, Shorten(TO_WSTRING(new_dir), COLS-const_strlen(msg)).c_str());
Mpd.UpdateDirectory(myTagEditor->CurrentDir()); Mpd.UpdateDirectory(myTagEditor->CurrentDir());
} }
else else
{ {
const char msg[] = "Couldn't rename \"%s\": %s"; const char msg[] = "Couldn't rename \"%s\": %s";
ShowMessage(msg, Shorten(TO_WSTRING(old_dir), COLS-static_strlen(msg)-25).c_str(), strerror(errno)); ShowMessage(msg, Shorten(TO_WSTRING(old_dir), COLS-const_strlen(msg)-25).c_str(), strerror(errno));
} }
} }
} }
@@ -1620,7 +1622,7 @@ void EditPlaylistName::Run()
if (Mpd.Rename(locale_to_utf_cpy(old_name), locale_to_utf_cpy(new_name))) if (Mpd.Rename(locale_to_utf_cpy(old_name), locale_to_utf_cpy(new_name)))
{ {
const char msg[] = "Playlist renamed to \"%s\""; const char msg[] = "Playlist renamed to \"%s\"";
ShowMessage(msg, Shorten(TO_WSTRING(new_name), COLS-static_strlen(msg)).c_str()); ShowMessage(msg, Shorten(TO_WSTRING(new_name), COLS-const_strlen(msg)).c_str());
if (myBrowser->Main() && !myBrowser->isLocal()) if (myBrowser->Main() && !myBrowser->isLocal())
myBrowser->GetDirectory("/"); myBrowser->GetDirectory("/");
if (myPlaylistEditor->Main()) if (myPlaylistEditor->Main())
@@ -1696,7 +1698,7 @@ void ToggleScreenLock::Run()
UnlockStatusbar(); UnlockStatusbar();
if (str_part.empty()) if (str_part.empty())
return; return;
part = StrToInt(str_part); part = stringToInt(str_part);
} }
if (part < 20 || part > 80) if (part < 20 || part > 80)
{ {
@@ -1760,7 +1762,7 @@ void JumpToPositionInSong::Run()
int newpos = 0; int newpos = 0;
if (position.find(':') != std::string::npos) // probably time in mm:ss if (position.find(':') != std::string::npos) // probably time in mm:ss
{ {
newpos = StrToInt(position)*60 + StrToInt(position.substr(position.find(':')+1)); newpos = stringToInt(position)*60 + stringToInt(position.substr(position.find(':')+1));
if (newpos >= 0 && newpos <= Mpd.GetTotalTime()) if (newpos >= 0 && newpos <= Mpd.GetTotalTime())
Mpd.Seek(newpos); Mpd.Seek(newpos);
else else
@@ -1768,7 +1770,7 @@ void JumpToPositionInSong::Run()
} }
else if (position.find('s') != std::string::npos) // probably position in seconds else if (position.find('s') != std::string::npos) // probably position in seconds
{ {
newpos = StrToInt(position); newpos = stringToInt(position);
if (newpos >= 0 && newpos <= Mpd.GetTotalTime()) if (newpos >= 0 && newpos <= Mpd.GetTotalTime())
Mpd.Seek(newpos); Mpd.Seek(newpos);
else else
@@ -1776,7 +1778,7 @@ void JumpToPositionInSong::Run()
} }
else else
{ {
newpos = StrToInt(position); newpos = stringToInt(position);
if (newpos >= 0 && newpos <= 100) if (newpos >= 0 && newpos <= 100)
Mpd.Seek(Mpd.GetTotalTime()*newpos/100.0); Mpd.Seek(Mpd.GetTotalTime()*newpos/100.0);
else else
@@ -2163,13 +2165,13 @@ void AddRandomItems::Run()
while (answer != 's' && answer != 'a' && answer != 'b'); while (answer != 's' && answer != 'a' && answer != 'b');
UnlockStatusbar(); UnlockStatusbar();
mpd_tag_type tag_type = IntoTagItem(answer); mpd_tag_type tag_type = charToTagType(answer);
std::string tag_type_str = answer == 's' ? "song" : IntoStr(tag_type); std::string tag_type_str = answer == 's' ? "song" : tagTypeToString(tag_type);
lowercase(tag_type_str); lowercase(tag_type_str);
LockStatusbar(); LockStatusbar();
Statusbar() << "Number of random " << tag_type_str << "s: "; Statusbar() << "Number of random " << tag_type_str << "s: ";
size_t number = StrToLong(wFooter->GetString()); size_t number = stringToLongInt(wFooter->GetString());
UnlockStatusbar(); UnlockStatusbar();
if (number && (answer == 's' ? Mpd.AddRandomSongs(number) : Mpd.AddRandomTag(tag_type, number))) if (number && (answer == 's' ? Mpd.AddRandomSongs(number) : Mpd.AddRandomTag(tag_type, number)))
ShowMessage("%zu random %s%s added to playlist", number, tag_type_str.c_str(), number == 1 ? "" : "s"); ShowMessage("%zu random %s%s added to playlist", number, tag_type_str.c_str(), number == 1 ? "" : "s");
@@ -2225,11 +2227,11 @@ void ToggleLibraryTagType::Run()
} }
while (answer != 'a' && answer != 'A' && answer != 'y' && answer != 'g' && answer != 'c' && answer != 'p'); while (answer != 'a' && answer != 'A' && answer != 'y' && answer != 'g' && answer != 'c' && answer != 'p');
UnlockStatusbar(); UnlockStatusbar();
mpd_tag_type new_tagitem = IntoTagItem(answer); mpd_tag_type new_tagitem = charToTagType(answer);
if (new_tagitem != Config.media_lib_primary_tag) if (new_tagitem != Config.media_lib_primary_tag)
{ {
Config.media_lib_primary_tag = new_tagitem; Config.media_lib_primary_tag = new_tagitem;
std::string item_type = IntoStr(Config.media_lib_primary_tag); std::string item_type = tagTypeToString(Config.media_lib_primary_tag);
myLibrary->Artists->SetTitle(Config.titles_visibility ? item_type + "s" : ""); myLibrary->Artists->SetTitle(Config.titles_visibility ? item_type + "s" : "");
myLibrary->Artists->Reset(); myLibrary->Artists->Reset();
lowercase(item_type); lowercase(item_type);

View File

@@ -516,12 +516,12 @@ void Browser::ClearDirectory(const std::string &path) const
if (remove(full_path.c_str()) == 0) if (remove(full_path.c_str()) == 0)
{ {
const char msg[] = "Deleting \"%s\"..."; const char msg[] = "Deleting \"%s\"...";
ShowMessage(msg, Shorten(TO_WSTRING(full_path), COLS-static_strlen(msg)).c_str()); ShowMessage(msg, Shorten(TO_WSTRING(full_path), COLS-const_strlen(msg)).c_str());
} }
else else
{ {
const char msg[] = "Couldn't remove \"%s\": %s"; const char msg[] = "Couldn't remove \"%s\": %s";
ShowMessage(msg, Shorten(TO_WSTRING(full_path), COLS-static_strlen(msg)-25).c_str(), strerror(errno)); ShowMessage(msg, Shorten(TO_WSTRING(full_path), COLS-const_strlen(msg)-25).c_str(), strerror(errno));
} }
} }
closedir(dir); closedir(dir);

View File

@@ -1,295 +0,0 @@
/***************************************************************************
* Copyright (C) 2008-2012 by Andrzej Rybczak *
* electricityispower@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include <algorithm>
#include "conv.h"
int StrToInt(const std::string &str)
{
return atoi(str.c_str());
}
long StrToLong(const std::string &str)
{
return atol(str.c_str());
}
std::string IntoStr(mpd_tag_type tag) // this is only for left column's title in media library
{
switch (tag)
{
case MPD_TAG_ARTIST:
return "Artist";
case MPD_TAG_ALBUM:
return "Album";
case MPD_TAG_ALBUM_ARTIST:
return "Album Artist";
case MPD_TAG_TITLE:
return "Title";
case MPD_TAG_TRACK:
return "Track";
case MPD_TAG_GENRE:
return "Genre";
case MPD_TAG_DATE:
return "Date";
case MPD_TAG_COMPOSER:
return "Composer";
case MPD_TAG_PERFORMER:
return "Performer";
case MPD_TAG_COMMENT:
return "Comment";
case MPD_TAG_DISC:
return "Disc";
default:
return "";
}
}
std::string IntoStr(NCurses::Color color)
{
std::string result;
if (color == NCurses::clDefault)
result = "default";
else if (color == NCurses::clBlack)
result = "black";
else if (color == NCurses::clRed)
result = "red";
else if (color == NCurses::clGreen)
result = "green";
else if (color == NCurses::clYellow)
result = "yellow";
else if (color == NCurses::clBlue)
result = "blue";
else if (color == NCurses::clMagenta)
result = "magenta";
else if (color == NCurses::clCyan)
result = "cyan";
else if (color == NCurses::clWhite)
result = "white";
return result;
}
std::string IntoStr(const Action::Key &key, bool *print_backspace)
{
std::string result;
if (key == Action::Key(KEY_UP, ctNCurses))
result += "Up";
else if (key == Action::Key(KEY_DOWN, ctNCurses))
result += "Down";
else if (key == Action::Key(KEY_PPAGE, ctNCurses))
result += "PageUp";
else if (key == Action::Key(KEY_NPAGE, ctNCurses))
result += "PageDown";
else if (key == Action::Key(KEY_HOME, ctNCurses))
result += "Home";
else if (key == Action::Key(KEY_END, ctNCurses))
result += "End";
else if (key == Action::Key(KEY_SPACE, ctStandard))
result += "Space";
else if (key == Action::Key(KEY_ENTER, ctStandard))
result += "Enter";
else if (key == Action::Key(KEY_DC, ctNCurses))
result += "Delete";
else if (key == Action::Key(KEY_RIGHT, ctNCurses))
result += "Right";
else if (key == Action::Key(KEY_LEFT, ctNCurses))
result += "Left";
else if (key == Action::Key(KEY_TAB, ctStandard))
result += "Tab";
else if (key == Action::Key(KEY_SHIFT_TAB, ctNCurses))
result += "Shift-Tab";
else if (key >= Action::Key(KEY_CTRL_A, ctStandard) && key <= Action::Key(KEY_CTRL_Z, ctStandard))
{
result += "Ctrl-";
result += key.getChar()+64;
}
else if (key >= Action::Key(KEY_F1, ctNCurses) && key <= Action::Key(KEY_F12, ctNCurses))
{
result += "F";
result += intTo<std::string>::apply(key.getChar()-264);
}
else if ((key == Action::Key(KEY_BACKSPACE, ctNCurses) || key == Action::Key(KEY_BACKSPACE_2, ctStandard)))
{
// since some terminals interpret KEY_BACKSPACE as backspace and other need KEY_BACKSPACE_2,
// actions have to be bound to either of them, but we want to display "Backspace" only once,
// hance this 'print_backspace' switch.
if (!print_backspace || *print_backspace)
{
result += "Backspace";
if (print_backspace)
*print_backspace = false;
}
}
else
result += ToString(std::wstring(1, key.getChar()));
return result;
}
NCurses::Color IntoColor(const std::string &color)
{
NCurses::Color result = NCurses::clDefault;
if (color == "black")
result = NCurses::clBlack;
else if (color == "red")
result = NCurses::clRed;
else if (color == "green")
result = NCurses::clGreen;
else if (color == "yellow")
result = NCurses::clYellow;
else if (color == "blue")
result = NCurses::clBlue;
else if (color == "magenta")
result = NCurses::clMagenta;
else if (color == "cyan")
result = NCurses::clCyan;
else if (color == "white")
result = NCurses::clWhite;
return result;
}
mpd_tag_type IntoTagItem(char c)
{
switch (c)
{
case 'a':
return MPD_TAG_ARTIST;
case 'A':
return MPD_TAG_ALBUM_ARTIST;
case 'b':
return MPD_TAG_ALBUM;
case 'y':
return MPD_TAG_DATE;
case 'g':
return MPD_TAG_GENRE;
case 'c':
return MPD_TAG_COMPOSER;
case 'p':
return MPD_TAG_PERFORMER;
default:
return MPD_TAG_ARTIST;
}
}
MPD::Song::GetFunction toGetFunction(char c)
{
switch (c)
{
case 'l':
return &MPD::Song::getLength;
case 'D':
return &MPD::Song::getDirectory;
case 'f':
return &MPD::Song::getName;
case 'a':
return &MPD::Song::getArtist;
case 'A':
return &MPD::Song::getAlbumArtist;
case 'b':
return &MPD::Song::getAlbum;
case 'y':
return &MPD::Song::getDate;
case 'n':
return &MPD::Song::getTrackNumber;
case 'N':
return &MPD::Song::getTrack;
case 'g':
return &MPD::Song::getGenre;
case 'c':
return &MPD::Song::getComposer;
case 'p':
return &MPD::Song::getPerformer;
case 'd':
return &MPD::Song::getDisc;
case 'C':
return &MPD::Song::getComment;
case 't':
return &MPD::Song::getTitle;
case 'P':
return &MPD::Song::getPriority;
default:
return 0;
}
}
#ifdef HAVE_TAGLIB_H
MPD::MutableSong::SetFunction IntoSetFunction(mpd_tag_type tag)
{
switch (tag)
{
case MPD_TAG_ARTIST:
return &MPD::MutableSong::setArtist;
case MPD_TAG_ALBUM:
return &MPD::MutableSong::setAlbum;
case MPD_TAG_ALBUM_ARTIST:
return &MPD::MutableSong::setAlbumArtist;
case MPD_TAG_TITLE:
return &MPD::MutableSong::setTitle;
case MPD_TAG_TRACK:
return &MPD::MutableSong::setTrack;
case MPD_TAG_GENRE:
return &MPD::MutableSong::setGenre;
case MPD_TAG_DATE:
return &MPD::MutableSong::setDate;
case MPD_TAG_COMPOSER:
return &MPD::MutableSong::setComposer;
case MPD_TAG_PERFORMER:
return &MPD::MutableSong::setPerformer;
case MPD_TAG_COMMENT:
return &MPD::MutableSong::setComment;
case MPD_TAG_DISC:
return &MPD::MutableSong::setDisc;
default:
return 0;
}
}
#endif // HAVE_TAGLIB_H
std::string Shorten(const std::basic_string<my_char_t> &s, size_t max_length)
{
if (s.length() <= max_length)
return TO_STRING(s);
if (max_length < 2)
return "";
std::basic_string<my_char_t> result(s, 0, max_length/2-!(max_length%2));
result += U("..");
result += s.substr(s.length()-max_length/2+1);
return TO_STRING(result);
}
void EscapeUnallowedChars(std::string &s)
{
static const std::string unallowed_chars = "\"*/:<>?\\|";
for (std::string::const_iterator it = unallowed_chars.begin(); it != unallowed_chars.end(); ++it)
{
for (size_t i = 0; i < s.length(); ++i)
{
if (s[i] == *it)
{
s.erase(s.begin()+i);
i--;
}
}
}
}

View File

@@ -25,6 +25,7 @@
#include "song_info.h" #include "song_info.h"
#include "playlist.h" #include "playlist.h"
#include "global.h" #include "global.h"
#include "utility/type_conversions.h"
using Global::myScreen; using Global::myScreen;
@@ -214,7 +215,7 @@ void Display::SongsInColumns(const MPD::Song &s, void *data, Menu<MPD::Song> *me
std::basic_string<my_char_t> tag; std::basic_string<my_char_t> tag;
for (size_t i = 0; i < it->type.length(); ++i) for (size_t i = 0; i < it->type.length(); ++i)
{ {
MPD::Song::GetFunction get = toGetFunction(it->type[i]); MPD::Song::GetFunction get = charToGetFunction(it->type[i]);
tag = TO_WSTRING(get ? s.getTags(get) : ""); tag = TO_WSTRING(get ? s.getTags(get) : "");
if (!tag.empty()) if (!tag.empty())
break; break;

View File

@@ -24,6 +24,7 @@
#include "ncmpcpp.h" #include "ncmpcpp.h"
#include "menu.h" #include "menu.h"
#include "mpdpp.h" #include "mpdpp.h"
#include "mutable_song.h"
#include "screen.h" #include "screen.h"
#include "search_engine.h" #include "search_engine.h"

View File

@@ -30,6 +30,66 @@ using Global::MainStartY;
Help *myHelp = new Help; Help *myHelp = new Help;
namespace {//
std::string keyToString(const Action::Key &key, bool *print_backspace)
{
std::string result;
if (key == Action::Key(KEY_UP, ctNCurses))
result += "Up";
else if (key == Action::Key(KEY_DOWN, ctNCurses))
result += "Down";
else if (key == Action::Key(KEY_PPAGE, ctNCurses))
result += "PageUp";
else if (key == Action::Key(KEY_NPAGE, ctNCurses))
result += "PageDown";
else if (key == Action::Key(KEY_HOME, ctNCurses))
result += "Home";
else if (key == Action::Key(KEY_END, ctNCurses))
result += "End";
else if (key == Action::Key(KEY_SPACE, ctStandard))
result += "Space";
else if (key == Action::Key(KEY_ENTER, ctStandard))
result += "Enter";
else if (key == Action::Key(KEY_DC, ctNCurses))
result += "Delete";
else if (key == Action::Key(KEY_RIGHT, ctNCurses))
result += "Right";
else if (key == Action::Key(KEY_LEFT, ctNCurses))
result += "Left";
else if (key == Action::Key(KEY_TAB, ctStandard))
result += "Tab";
else if (key == Action::Key(KEY_SHIFT_TAB, ctNCurses))
result += "Shift-Tab";
else if (key >= Action::Key(KEY_CTRL_A, ctStandard) && key <= Action::Key(KEY_CTRL_Z, ctStandard))
{
result += "Ctrl-";
result += key.getChar()+64;
}
else if (key >= Action::Key(KEY_F1, ctNCurses) && key <= Action::Key(KEY_F12, ctNCurses))
{
result += "F";
result += intTo<std::string>::apply(key.getChar()-264);
}
else if ((key == Action::Key(KEY_BACKSPACE, ctNCurses) || key == Action::Key(KEY_BACKSPACE_2, ctStandard)))
{
// since some terminals interpret KEY_BACKSPACE as backspace and other need KEY_BACKSPACE_2,
// actions have to be bound to either of them, but we want to display "Backspace" only once,
// hance this 'print_backspace' switch.
if (!print_backspace || *print_backspace)
{
result += "Backspace";
if (print_backspace)
*print_backspace = false;
}
}
else
result += ToString(std::wstring(1, key.getChar()));
return result;
}
}
void Help::Init() void Help::Init()
{ {
w = new Scrollpad(0, MainStartY, COLS, MainHeight, "", Config.main_color, brNone); w = new Scrollpad(0, MainStartY, COLS, MainHeight, "", Config.main_color, brNone);
@@ -84,7 +144,7 @@ std::string Help::DisplayKeys(const ActionType at)
{ {
if (it->second.isSingle() && it->second.getAction()->Type() == at) if (it->second.isSingle() && it->second.getAction()->Type() == at)
{ {
result += IntoStr(it->first, &print_backspace); result += keyToString(it->first, &print_backspace);
result += " "; result += " ";
} }
} }

View File

@@ -353,3 +353,15 @@ std::basic_string<my_char_t> Scroller(const std::basic_string<my_char_t> &str, s
result = s; result = s;
return result; return result;
} }
std::string Shorten(const std::basic_string<my_char_t> &s, size_t max_length)
{
if (s.length() <= max_length)
return TO_STRING(s);
if (max_length < 2)
return "";
std::basic_string<my_char_t> result(s, 0, max_length/2-!(max_length%2));
result += U("..");
result += s.substr(s.length()-max_length/2+1);
return TO_STRING(result);
}

View File

@@ -21,7 +21,6 @@
#ifndef _HELPERS_H #ifndef _HELPERS_H
#define _HELPERS_H #define _HELPERS_H
#include "conv.h"
#include "mpdpp.h" #include "mpdpp.h"
#include "ncmpcpp.h" #include "ncmpcpp.h"
#include "settings.h" #include "settings.h"
@@ -194,4 +193,6 @@ template <typename T> std::string getSharedDirectory(Menu<T> *menu)
std::basic_string<my_char_t> Scroller(const std::basic_string<my_char_t> &str, size_t &pos, size_t width); std::basic_string<my_char_t> Scroller(const std::basic_string<my_char_t> &str, size_t &pos, size_t width);
std::string Shorten(const std::basic_string<my_char_t> &s, size_t max_length);
#endif #endif

View File

@@ -30,6 +30,7 @@
#include <cassert> #include <cassert>
#include <cerrno> #include <cerrno>
#include <cstring>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
@@ -125,7 +126,7 @@ void Lastfm::Load()
std::string file = artist + ".txt"; std::string file = artist + ".txt";
lowercase(file); lowercase(file);
EscapeUnallowedChars(file); removeInvalidCharsFromFilename(file);
itsFilename = itsFolder + "/" + file; itsFilename = itsFolder + "/" + file;
@@ -211,7 +212,7 @@ void Lastfm::Refetch()
if (remove(itsFilename.c_str()) && errno != ENOENT) if (remove(itsFilename.c_str()) && errno != ENOENT)
{ {
const char msg[] = "Couldn't remove \"%s\": %s"; const char msg[] = "Couldn't remove \"%s\": %s";
ShowMessage(msg, Shorten(TO_WSTRING(itsFilename), COLS-static_strlen(msg)-25).c_str(), strerror(errno)); ShowMessage(msg, Shorten(TO_WSTRING(itsFilename), COLS-const_strlen(msg)-25).c_str(), strerror(errno));
return; return;
} }
Load(); Load();

View File

@@ -22,7 +22,6 @@
#ifdef HAVE_CURL_CURL_H #ifdef HAVE_CURL_CURL_H
#include "conv.h"
#include "curl_handle.h" #include "curl_handle.h"
#include "settings.h" #include "settings.h"
#include "utility/html.h" #include "utility/html.h"
@@ -118,7 +117,7 @@ bool ArtistInfo::parse(std::string &data)
if ((a = data.find("<content>")) != std::string::npos) if ((a = data.find("<content>")) != std::string::npos)
{ {
a += static_strlen("<content>"); a += const_strlen("<content>");
if ((b = data.find("</content>")) == std::string::npos) if ((b = data.find("</content>")) == std::string::npos)
parse_failed = true; parse_failed = true;
} }
@@ -142,17 +141,17 @@ bool ArtistInfo::parse(std::string &data)
i != std::string::npos; i = data.find("<name>", i), k = data.find("<url>", k)) i != std::string::npos; i = data.find("<name>", i), k = data.find("<url>", k))
{ {
j = data.find("</name>", i); j = data.find("</name>", i);
i += static_strlen("<name>"); i += const_strlen("<name>");
l = data.find("</url>", k); l = data.find("</url>", k);
k += static_strlen("<url>"); k += const_strlen("<url>");
similars.push_back(std::make_pair(data.substr(i, j-i), data.substr(k, l-k))); similars.push_back(std::make_pair(data.substr(i, j-i), data.substr(k, l-k)));
stripHtmlTags(similars.back().first); stripHtmlTags(similars.back().first);
} }
a += static_strlen("<![CDATA["); a += const_strlen("<![CDATA[");
b -= static_strlen("]]>"); b -= const_strlen("]]>");
data = data.substr(a, b-a); data = data.substr(a, b-a);
postProcess(data); postProcess(data);

View File

@@ -20,6 +20,7 @@
#include <cassert> #include <cassert>
#include <cerrno> #include <cerrno>
#include <cstring>
#include <fstream> #include <fstream>
#include "browser.h" #include "browser.h"
@@ -305,7 +306,7 @@ std::string Lyrics::GenerateFilename(const MPD::Song &s)
file += " - "; file += " - ";
file += locale_to_utf_cpy(s.getTitle()); file += locale_to_utf_cpy(s.getTitle());
file += ".txt"; file += ".txt";
EscapeUnallowedChars(file); removeInvalidCharsFromFilename(file);
filename = Config.lyrics_directory; filename = Config.lyrics_directory;
filename += "/"; filename += "/";
filename += file; filename += file;
@@ -402,7 +403,7 @@ void Lyrics::Refetch()
if (remove(itsFilename.c_str()) && errno != ENOENT) if (remove(itsFilename.c_str()) && errno != ENOENT)
{ {
const char msg[] = "Couldn't remove \"%s\": %s"; const char msg[] = "Couldn't remove \"%s\": %s";
ShowMessage(msg, Shorten(TO_WSTRING(itsFilename), COLS-static_strlen(msg)-25).c_str(), strerror(errno)); ShowMessage(msg, Shorten(TO_WSTRING(itsFilename), COLS-const_strlen(msg)-25).c_str(), strerror(errno));
return; return;
} }
Load(); Load();

View File

@@ -23,11 +23,12 @@
#ifdef HAVE_CURL_CURL_H #ifdef HAVE_CURL_CURL_H
#include <cstdlib> #include <cstdlib>
#include <cstring>
#include "charset.h" #include "charset.h"
#include "conv.h"
#include "lyrics_fetcher.h" #include "lyrics_fetcher.h"
#include "utility/html.h" #include "utility/html.h"
#include "utility/string.h"
LyricsFetcher *lyricsPlugins[] = LyricsFetcher *lyricsPlugins[] =
{ {
@@ -270,7 +271,7 @@ void LyricsvipFetcher::postProcess(std::string &data)
// throw away <div> with ad // throw away <div> with ad
size_t i = data.find("<div class=\"ad\""), j = data.find("</div>"); size_t i = data.find("<div class=\"ad\""), j = data.find("</div>");
if (i != std::string::npos && i != std::string::npos) if (i != std::string::npos && i != std::string::npos)
data.replace(i, j-i+static_strlen("</div>"), ""); data.replace(i, j-i+const_strlen("</div>"), "");
data = unescapeHtmlUtf8(data); data = unescapeHtmlUtf8(data);
LyricsFetcher::postProcess(data); LyricsFetcher::postProcess(data);
} }

View File

@@ -30,6 +30,7 @@
#include "playlist.h" #include "playlist.h"
#include "status.h" #include "status.h"
#include "utility/comparators.h" #include "utility/comparators.h"
#include "utility/type_conversions.h"
using Global::MainHeight; using Global::MainHeight;
using Global::MainStartY; using Global::MainStartY;
@@ -60,7 +61,7 @@ void MediaLibrary::Init()
itsRightColWidth = COLS-COLS/3*2-1; itsRightColWidth = COLS-COLS/3*2-1;
itsRightColStartX = itsLeftColWidth+itsMiddleColWidth+2; itsRightColStartX = itsLeftColWidth+itsMiddleColWidth+2;
Artists = new Menu<std::string>(0, MainStartY, itsLeftColWidth, MainHeight, Config.titles_visibility ? IntoStr(Config.media_lib_primary_tag) + "s" : "", Config.main_color, brNone); Artists = new Menu<std::string>(0, MainStartY, itsLeftColWidth, MainHeight, Config.titles_visibility ? tagTypeToString(Config.media_lib_primary_tag) + "s" : "", Config.main_color, brNone);
Artists->HighlightColor(Config.active_column_color); Artists->HighlightColor(Config.active_column_color);
Artists->CyclicScrolling(Config.use_cyclic_scrolling); Artists->CyclicScrolling(Config.use_cyclic_scrolling);
Artists->CenteredCursor(Config.centered_cursor); Artists->CenteredCursor(Config.centered_cursor);
@@ -162,7 +163,7 @@ void MediaLibrary::SwitchTo()
NextColumn(); NextColumn();
if (Config.titles_visibility) if (Config.titles_visibility)
{ {
std::string item_type = IntoStr(Config.media_lib_primary_tag); std::string item_type = tagTypeToString(Config.media_lib_primary_tag);
lowercase(item_type); lowercase(item_type);
Albums->SetTitle("Albums (sorted by " + item_type + ")"); Albums->SetTitle("Albums (sorted by " + item_type + ")");
} }
@@ -635,7 +636,7 @@ void MediaLibrary::LocateSong(const MPD::Song &s)
} }
if (primary_tag.empty()) if (primary_tag.empty())
{ {
std::string item_type = IntoStr(Config.media_lib_primary_tag); std::string item_type = tagTypeToString(Config.media_lib_primary_tag);
lowercase(item_type); lowercase(item_type);
ShowMessage("Can't use this function because the song has no %s tag set", item_type.c_str()); ShowMessage("Can't use this function because the song has no %s tag set", item_type.c_str());
return; return;
@@ -726,7 +727,7 @@ void MediaLibrary::AddToPlaylist(bool add_n_play)
if ((!Artists->Empty() && w == Artists) if ((!Artists->Empty() && w == Artists)
|| (w == Albums && Albums->Current().Date == AllTracksMarker)) || (w == Albums && Albums->Current().Date == AllTracksMarker))
{ {
std::string tag_type = IntoStr(Config.media_lib_primary_tag); std::string tag_type = tagTypeToString(Config.media_lib_primary_tag);
lowercase(tag_type); lowercase(tag_type);
ShowMessage("Songs with %s = \"%s\" added", tag_type.c_str(), Artists->Current().c_str()); ShowMessage("Songs with %s = \"%s\" added", tag_type.c_str(), Artists->Current().c_str());
} }
@@ -790,9 +791,9 @@ bool MediaLibrary::SearchConstraintsSorting::operator()(const SearchConstraints
bool MediaLibrary::SortSongsByTrack(const MPD::Song &a, const MPD::Song &b) bool MediaLibrary::SortSongsByTrack(const MPD::Song &a, const MPD::Song &b)
{ {
if (a.getDisc() == b.getDisc()) if (a.getDisc() == b.getDisc())
return StrToInt(a.getTrack()) < StrToInt(b.getTrack()); return stringToInt(a.getTrack()) < stringToInt(b.getTrack());
else else
return StrToInt(a.getDisc()) < StrToInt(b.getDisc()); return stringToInt(a.getDisc()) < stringToInt(b.getDisc());
} }
bool MediaLibrary::SortAllTracks(const MPD::Song &a, const MPD::Song &b) bool MediaLibrary::SortAllTracks(const MPD::Song &a, const MPD::Song &b)

View File

@@ -26,6 +26,7 @@
# include <sys/stat.h> # include <sys/stat.h>
#endif // WIN32 #endif // WIN32
#include <cstdlib> #include <cstdlib>
#include <cstring>
#include <string> #include <string>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
@@ -46,6 +47,7 @@
#include "settings.h" #include "settings.h"
#include "tag_editor.h" #include "tag_editor.h"
#include "visualizer.h" #include "visualizer.h"
#include "utility/type_conversions.h"
#ifdef HAVE_LANGINFO_H #ifdef HAVE_LANGINFO_H
# include <langinfo.h> # include <langinfo.h>
@@ -56,12 +58,36 @@ KeyConfiguration Keys;
namespace namespace
{ {
Border IntoBorder(const std::string &color) NCurses::Color stringToColor(const std::string &color)
{ {
return Border(IntoColor(color)); NCurses::Color result = NCurses::clDefault;
if (color == "black")
result = NCurses::clBlack;
else if (color == "red")
result = NCurses::clRed;
else if (color == "green")
result = NCurses::clGreen;
else if (color == "yellow")
result = NCurses::clYellow;
else if (color == "blue")
result = NCurses::clBlue;
else if (color == "magenta")
result = NCurses::clMagenta;
else if (color == "cyan")
result = NCurses::clCyan;
else if (color == "white")
result = NCurses::clWhite;
return result;
} }
BasicScreen *IntoScreen(int n) Border stringToBorder(const std::string &border)
{
return Border(stringToColor(border));
}
BasicScreen *intToScreen(int n)
{ {
switch (n) switch (n)
{ {
@@ -488,33 +514,33 @@ void Configuration::Read()
} }
else if (name == "mpd_port") else if (name == "mpd_port")
{ {
if (StrToInt(v)) if (stringToInt(v))
mpd_port = StrToInt(v); mpd_port = stringToInt(v);
} }
else if (name == "mpd_connection_timeout") else if (name == "mpd_connection_timeout")
{ {
if (StrToInt(v)) if (stringToInt(v))
mpd_connection_timeout = StrToInt(v); mpd_connection_timeout = stringToInt(v);
} }
else if (name == "mpd_crossfade_time") else if (name == "mpd_crossfade_time")
{ {
if (StrToInt(v) > 0) if (stringToInt(v) > 0)
crossfade_time = StrToInt(v); crossfade_time = stringToInt(v);
} }
else if (name == "seek_time") else if (name == "seek_time")
{ {
if (StrToInt(v) > 0) if (stringToInt(v) > 0)
seek_time = StrToInt(v); seek_time = stringToInt(v);
} }
else if (name == "playlist_disable_highlight_delay") else if (name == "playlist_disable_highlight_delay")
{ {
if (StrToInt(v) >= 0) if (stringToInt(v) >= 0)
playlist_disable_highlight_delay = StrToInt(v); playlist_disable_highlight_delay = stringToInt(v);
} }
else if (name == "message_delay_time") else if (name == "message_delay_time")
{ {
if (StrToInt(v) > 0) if (stringToInt(v) > 0)
message_delay_time = StrToInt(v); message_delay_time = stringToInt(v);
} }
else if (name == "song_list_format") else if (name == "song_list_format")
{ {
@@ -689,12 +715,12 @@ void Configuration::Read()
else if (name == "color1") else if (name == "color1")
{ {
if (!v.empty()) if (!v.empty())
color1 = IntoColor(v); color1 = stringToColor(v);
} }
else if (name == "color2") else if (name == "color2")
{ {
if (!v.empty()) if (!v.empty())
color2 = IntoColor(v); color2 = stringToColor(v);
} }
else if (name == "mpd_communication_mode") else if (name == "mpd_communication_mode")
{ {
@@ -768,7 +794,7 @@ void Configuration::Read()
++it; ++it;
if (it == v.end()) if (it == v.end())
break; break;
if (BasicScreen *screen = IntoScreen(atoi(&*it))) if (BasicScreen *screen = intToScreen(atoi(&*it)))
screens_seq.push_back(screen); screens_seq.push_back(screen);
while (it != v.end() && isdigit(*it)) while (it != v.end() && isdigit(*it))
++it; ++it;
@@ -779,7 +805,7 @@ void Configuration::Read()
} }
else if (name == "startup_screen") else if (name == "startup_screen")
{ {
startup_screen = IntoScreen(atoi(v.c_str())); startup_screen = intToScreen(atoi(v.c_str()));
if (!startup_screen) if (!startup_screen)
startup_screen = myPlaylist; startup_screen = myPlaylist;
} }
@@ -932,20 +958,20 @@ void Configuration::Read()
else if (name == "lines_scrolled") else if (name == "lines_scrolled")
{ {
if (!v.empty()) if (!v.empty())
lines_scrolled = StrToInt(v); lines_scrolled = stringToInt(v);
} }
else if (name == "search_engine_default_search_mode") else if (name == "search_engine_default_search_mode")
{ {
if (!v.empty()) if (!v.empty())
{ {
unsigned mode = StrToInt(v); unsigned mode = stringToInt(v);
if (--mode < 3) if (--mode < 3)
search_engine_default_search_mode = mode; search_engine_default_search_mode = mode;
} }
} }
else if (name == "visualizer_sync_interval") else if (name == "visualizer_sync_interval")
{ {
unsigned interval = StrToInt(v); unsigned interval = stringToInt(v);
if (interval) if (interval)
visualizer_sync_interval = interval; visualizer_sync_interval = interval;
} }
@@ -960,7 +986,7 @@ void Configuration::Read()
} }
else if (name == "locked_screen_width_part") else if (name == "locked_screen_width_part")
{ {
int part = StrToInt(v); int part = stringToInt(v);
if (part) if (part)
locked_screen_width_part = part/100.0; locked_screen_width_part = part/100.0;
} }
@@ -990,82 +1016,82 @@ void Configuration::Read()
else if (name == "empty_tag_color") else if (name == "empty_tag_color")
{ {
if (!v.empty()) if (!v.empty())
empty_tags_color = IntoColor(v); empty_tags_color = stringToColor(v);
} }
else if (name == "header_window_color") else if (name == "header_window_color")
{ {
if (!v.empty()) if (!v.empty())
header_color = IntoColor(v); header_color = stringToColor(v);
} }
else if (name == "volume_color") else if (name == "volume_color")
{ {
if (!v.empty()) if (!v.empty())
volume_color = IntoColor(v); volume_color = stringToColor(v);
} }
else if (name == "state_line_color") else if (name == "state_line_color")
{ {
if (!v.empty()) if (!v.empty())
state_line_color = IntoColor(v); state_line_color = stringToColor(v);
} }
else if (name == "state_flags_color") else if (name == "state_flags_color")
{ {
if (!v.empty()) if (!v.empty())
state_flags_color = IntoColor(v); state_flags_color = stringToColor(v);
} }
else if (name == "main_window_color") else if (name == "main_window_color")
{ {
if (!v.empty()) if (!v.empty())
main_color = IntoColor(v); main_color = stringToColor(v);
} }
else if (name == "main_window_highlight_color") else if (name == "main_window_highlight_color")
{ {
if (!v.empty()) if (!v.empty())
main_highlight_color = IntoColor(v); main_highlight_color = stringToColor(v);
} }
else if (name == "progressbar_color") else if (name == "progressbar_color")
{ {
if (!v.empty()) if (!v.empty())
progressbar_color = IntoColor(v); progressbar_color = stringToColor(v);
} }
else if (name == "progressbar_elapsed_color") else if (name == "progressbar_elapsed_color")
{ {
if (!v.empty()) if (!v.empty())
progressbar_elapsed_color = IntoColor(v); progressbar_elapsed_color = stringToColor(v);
} }
else if (name == "statusbar_color") else if (name == "statusbar_color")
{ {
if (!v.empty()) if (!v.empty())
statusbar_color = IntoColor(v); statusbar_color = stringToColor(v);
} }
else if (name == "alternative_ui_separator_color") else if (name == "alternative_ui_separator_color")
{ {
if (!v.empty()) if (!v.empty())
alternative_ui_separator_color = IntoColor(v); alternative_ui_separator_color = stringToColor(v);
} }
else if (name == "active_column_color") else if (name == "active_column_color")
{ {
if (!v.empty()) if (!v.empty())
active_column_color = IntoColor(v); active_column_color = stringToColor(v);
} }
else if (name == "visualizer_color") else if (name == "visualizer_color")
{ {
if (!v.empty()) if (!v.empty())
visualizer_color = IntoColor(v); visualizer_color = stringToColor(v);
} }
else if (name == "window_border_color") else if (name == "window_border_color")
{ {
if (!v.empty()) if (!v.empty())
window_border = IntoBorder(v); window_border = stringToBorder(v);
} }
else if (name == "active_window_border") else if (name == "active_window_border")
{ {
if (!v.empty()) if (!v.empty())
active_window_border = IntoBorder(v); active_window_border = stringToBorder(v);
} }
else if (name == "media_library_left_column") else if (name == "media_library_left_column")
{ {
if (!v.empty()) if (!v.empty())
media_lib_primary_tag = IntoTagItem(v[0]); media_lib_primary_tag = charToTagType(v[0]);
} }
else else
std::cout << "Unknown option: " << name << ", ignoring.\n"; std::cout << "Unknown option: " << name << ", ignoring.\n";
@@ -1082,7 +1108,7 @@ void Configuration::GenerateColumns()
while (!(width = getEnclosedString(song_list_columns_format, '(', ')', &pos)).empty()) while (!(width = getEnclosedString(song_list_columns_format, '(', ')', &pos)).empty())
{ {
Column col; Column col;
col.color = IntoColor(getEnclosedString(song_list_columns_format, '[', ']', &pos)); col.color = stringToColor(getEnclosedString(song_list_columns_format, '[', ']', &pos));
std::string tag_type = getEnclosedString(song_list_columns_format, '{', '}', &pos); std::string tag_type = getEnclosedString(song_list_columns_format, '{', '}', &pos);
col.fixed = *width.rbegin() == 'f'; col.fixed = *width.rbegin() == 'f';
@@ -1121,7 +1147,7 @@ void Configuration::GenerateColumns()
else // empty column else // empty column
col.display_empty_tag = 0; col.display_empty_tag = 0;
col.width = StrToInt(width); col.width = stringToInt(width);
columns.push_back(col); columns.push_back(col);
} }

View File

@@ -24,7 +24,9 @@
#include <memory> #include <memory>
#include "song.h" #include "song.h"
#include "conv.h" #include "utility/numeric_conversions.h"
#include "utility/type_conversions.h"
#include "window.h"
namespace {// namespace {//
@@ -282,12 +284,10 @@ std::string Song::ShowTime(unsigned length)
length -= minutes*60; length -= minutes*60;
int seconds = length; int seconds = length;
char buf[32];
if (hours > 0) if (hours > 0)
snprintf(buf, sizeof(buf), "%d:%02d:%02d", hours, minutes, seconds); return print<32, std::string>::apply("%d:%02d:%02d", hours, minutes, seconds);
else else
snprintf(buf, sizeof(buf), "%d:%02d", minutes, seconds); return print<32, std::string>::apply("%d:%02d", minutes, seconds);
return buf;
} }
bool MPD::Song::isFormatOk(const std::string &type, const std::string &fmt) bool MPD::Song::isFormatOk(const std::string &type, const std::string &fmt)
@@ -310,7 +310,7 @@ bool MPD::Song::isFormatOk(const std::string &type, const std::string &fmt)
{ {
if (isdigit(fmt[++i])) if (isdigit(fmt[++i]))
while (isdigit(fmt[++i])) { } while (isdigit(fmt[++i])) { }
if (!toGetFunction(fmt[i])) if (!charToGetFunction(fmt[i]))
{ {
std::cerr << type << ": invalid character at position " << unsignedLongIntTo<std::string>::apply(i+1) << ": '" << fmt[i] << "'\n"; std::cerr << type << ": invalid character at position " << unsignedLongIntTo<std::string>::apply(i+1) << ": '" << fmt[i] << "'\n";
return false; return false;
@@ -353,7 +353,7 @@ std::string Song::ParseFormat(std::string::const_iterator &it, const std::string
get = 0; get = 0;
} }
else else
get = toGetFunction(*it); get = charToGetFunction(*it);
if (get) if (get)
{ {
@@ -368,9 +368,9 @@ std::string Song::ParseFormat(std::string::const_iterator &it, const std::string
{ {
if (delimiter) if (delimiter)
{ {
const std::basic_string<my_char_t> &s = TO_WSTRING(tag); /*const std::basic_string<my_char_t> &s = TO_WSTRING(tag);
if (NCurses::Window::Length(s) > delimiter) if (NCurses::Window::Length(s) > delimiter)
tag = Shorten(s, delimiter); tag = Shorten(s, delimiter);*/
} }
has_some_tags = 1; has_some_tags = 1;
result += tag; result += tag;

View File

@@ -22,7 +22,7 @@
#define _SONG_INFO_H #define _SONG_INFO_H
#include "screen.h" #include "screen.h"
#include "song.h" #include "mutable_song.h"
class SongInfo : public Screen<Scrollpad> class SongInfo : public Screen<Scrollpad>
{ {

View File

@@ -21,9 +21,8 @@
#ifndef _STRBUFFER_H #ifndef _STRBUFFER_H
#define _STRBUFFER_H #define _STRBUFFER_H
#include "numeric_conversions.h"
#include "window.h" #include "window.h"
#include "utility/string.h" #include "utility/numeric_conversions.h"
#include <list> #include <list>

View File

@@ -625,7 +625,7 @@ void TagEditor::EnterPressed()
if (!WriteTags(**it)) if (!WriteTags(**it))
{ {
const char msg[] = "Error while writing tags in \"%s\""; const char msg[] = "Error while writing tags in \"%s\"";
ShowMessage(msg, Shorten(TO_WSTRING((*it)->getURI()), COLS-static_strlen(msg)).c_str()); ShowMessage(msg, Shorten(TO_WSTRING((*it)->getURI()), COLS-const_strlen(msg)).c_str());
success = 0; success = 0;
break; break;
} }
@@ -1026,8 +1026,8 @@ bool TagEditor::WriteTags(MPD::MutableSong &s)
f.tag()->setTitle(ToWString(s.getTitle())); f.tag()->setTitle(ToWString(s.getTitle()));
f.tag()->setArtist(ToWString(s.getArtist())); f.tag()->setArtist(ToWString(s.getArtist()));
f.tag()->setAlbum(ToWString(s.getAlbum())); f.tag()->setAlbum(ToWString(s.getAlbum()));
f.tag()->setYear(StrToInt(s.getDate())); f.tag()->setYear(stringToInt(s.getDate()));
f.tag()->setTrack(StrToInt(s.getTrack())); f.tag()->setTrack(stringToInt(s.getTrack()));
f.tag()->setGenre(ToWString(s.getGenre())); f.tag()->setGenre(ToWString(s.getGenre()));
f.tag()->setComment(ToWString(s.getComment())); f.tag()->setComment(ToWString(s.getComment()));
if (TagLib::MPEG::File *mp3_file = dynamic_cast<TagLib::MPEG::File *>(f.file())) if (TagLib::MPEG::File *mp3_file = dynamic_cast<TagLib::MPEG::File *>(f.file()))
@@ -1219,7 +1219,7 @@ MPD::MutableSong::SetFunction TagEditor::IntoSetFunction(char c)
std::string TagEditor::GenerateFilename(const MPD::MutableSong &s, const std::string &pattern) std::string TagEditor::GenerateFilename(const MPD::MutableSong &s, const std::string &pattern)
{ {
std::string result = s.toString(pattern); std::string result = s.toString(pattern);
EscapeUnallowedChars(result); removeInvalidCharsFromFilename(result);
return result; return result;
} }

View File

@@ -33,6 +33,7 @@
#include "tag.h" #include "tag.h"
#include "mpdpp.h" #include "mpdpp.h"
#include "mutable_song.h"
#include "screen.h" #include "screen.h"
class TagEditor : public Screen<Window> class TagEditor : public Screen<Window>

View File

@@ -28,6 +28,7 @@
// taglib includes // taglib includes
#include "tfile.h" #include "tfile.h"
#include "mutable_song.h"
#include "screen.h" #include "screen.h"
class TinyTagEditor : public Screen< Menu<Buffer> > class TinyTagEditor : public Screen< Menu<Buffer> >

View File

@@ -18,75 +18,58 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/ ***************************************************************************/
#include <cstdio>
#include <cwchar>
#include <string> #include <string>
#include "string.h"
#ifndef _NUMERIC_CONVERSIONS_H #ifndef _UTILITY_NUMERIC_CONVERSIONS_H
#define _NUMERIC_CONVERSIONS_H #define _UTILITY_NUMERIC_CONVERSIONS_H
template <typename R> struct intTo { }; template <typename R> struct intTo { };
template <> struct intTo<std::string> { template <> struct intTo<std::string> {
static std::string apply(int n) { static std::string apply(int n) {
char buf[32]; return print<32, std::string>::apply("%d", n);
snprintf(buf, sizeof(buf), "%d", n);
return buf;
} }
}; };
template <> struct intTo<std::wstring> { template <> struct intTo<std::wstring> {
static std::wstring apply(int n) { static std::wstring apply(int n) {
wchar_t buf[32]; return print<32, std::wstring>::apply(L"%d", n);
swprintf(buf, sizeof(buf)/sizeof(wchar_t), L"%d", n);
return buf;
} }
}; };
template <typename R> struct longIntTo { }; template <typename R> struct longIntTo { };
template <> struct longIntTo<std::string> { template <> struct longIntTo<std::string> {
static std::string apply(long int n) { static std::string apply(long int n) {
char buf[32]; return print<32, std::string>::apply("%ld", n);
snprintf(buf, sizeof(buf), "%ld", n);
return buf;
} }
}; };
template <> struct longIntTo<std::wstring> { template <> struct longIntTo<std::wstring> {
static std::wstring apply(long int n) { static std::wstring apply(long int n) {
wchar_t buf[32]; return print<32, std::wstring>::apply(L"%ld", n);
swprintf(buf, sizeof(buf)/sizeof(wchar_t), L"%ld", n);
return buf;
} }
}; };
template <typename R> struct unsignedIntTo { }; template <typename R> struct unsignedIntTo { };
template <> struct unsignedIntTo<std::string> { template <> struct unsignedIntTo<std::string> {
static std::string apply(unsigned int n) { static std::string apply(unsigned int n) {
char buf[32]; return print<32, std::string>::apply("%u", n);
snprintf(buf, sizeof(buf), "%u", n);
return buf;
} }
}; };
template <> struct unsignedIntTo<std::wstring> { template <> struct unsignedIntTo<std::wstring> {
static std::wstring apply(unsigned int n) { static std::wstring apply(unsigned int n) {
wchar_t buf[32]; return print<32, std::wstring>::apply(L"%u", n);
swprintf(buf, sizeof(buf)/sizeof(wchar_t), L"%u", n);
return buf;
} }
}; };
template <typename R> struct unsignedLongIntTo { }; template <typename R> struct unsignedLongIntTo { };
template <> struct unsignedLongIntTo<std::string> { template <> struct unsignedLongIntTo<std::string> {
static std::string apply(unsigned long int n) { static std::string apply(unsigned long int n) {
char buf[32]; return print<32, std::string>::apply("%lu", n);
snprintf(buf, sizeof(buf), "%lu", n);
return buf;
} }
}; };
template <> struct unsignedLongIntTo<std::wstring> { template <> struct unsignedLongIntTo<std::wstring> {
static std::wstring apply(unsigned long int n) { static std::wstring apply(unsigned long int n) {
wchar_t buf[32]; return print<32, std::wstring>::apply(L"%lu", n);
swprintf(buf, sizeof(buf)/sizeof(wchar_t), L"%lu", n);
return buf;
} }
}; };
#endif // _NUMERIC_CONVERSIONS_H #endif // _UTILITY_NUMERIC_CONVERSIONS_H

View File

@@ -23,6 +23,52 @@
#include <algorithm> #include <algorithm>
#include "utility/string.h" #include "utility/string.h"
int stringToInt(const std::string &s)
{
return atoi(s.c_str());
}
long stringToLongInt(const std::string &s)
{
return atol(s.c_str());
}
bool isInteger(const char *s)
{
assert(s);
if (*s == '\0')
return false;
for (const char *it = s; *it != '\0'; ++it)
if (!isdigit(*it) && (it != s || *it != '-'))
return false;
return true;
}
std::string ToString(const std::wstring &ws)
{
std::string result;
char s[MB_CUR_MAX];
for (size_t i = 0; i < ws.length(); ++i)
{
int n = wcrtomb(s, ws[i], 0);
if (n > 0)
result.append(s, n);
}
return result;
}
std::wstring ToWString(const std::string &s)
{
std::wstring result;
wchar_t *ws = new wchar_t[s.length()];
const char *c_s = s.c_str();
int n = mbsrtowcs(ws, &c_s, s.length(), 0);
if (n > 0)
result.append(ws, n);
delete [] ws;
return result;
}
std::vector<std::string> split(const std::string &s, const std::string &delimiter) std::vector<std::string> split(const std::string &s, const std::string &delimiter)
{ {
if (delimiter.empty()) if (delimiter.empty())
@@ -134,13 +180,18 @@ std::string getEnclosedString(const std::string &s, char a, char b, size_t *pos)
return result; return result;
} }
bool isInteger(const char *s) void removeInvalidCharsFromFilename(std::string &filename)
{ {
assert(s); const char *unallowed_chars = "\"*/:<>?\\|";
if (*s == '\0') for (const char *c = unallowed_chars; *c; ++c)
return false; {
for (const char *it = s; *it != '\0'; ++it) for (size_t i = 0; i < filename.length(); ++i)
if (!isdigit(*it) && (it != s || *it != '-')) {
return false; if (filename[i] == *c)
return true; {
filename.erase(filename.begin()+i);
--i;
}
}
}
} }

View File

@@ -21,8 +21,43 @@
#ifndef _UTILITY_STRING #ifndef _UTILITY_STRING
#define _UTILITY_STRING #define _UTILITY_STRING
#include <cstdarg>
#include <string> #include <string>
#include <vector> #include <vector>
#include "gcc.h"
template <size_t N> size_t const_strlen(const char (&)[N]) {
return N-1;
}
template <size_t N, typename T> struct print { };
template <size_t N> struct print<N, std::string> {
static std::string apply(const char *format, ...) GNUC_PRINTF(1, 2) {
char buf[N];
va_list args;
va_start(args, format);
vsnprintf(buf, sizeof(buf)/sizeof(char), format, args);
va_end(args);
return buf;
}
};
template <size_t N> struct print<N, std::wstring> {
static std::wstring apply(const wchar_t *format, ...) {
wchar_t buf[N];
va_list args;
va_start(args, format);
vswprintf(buf, sizeof(buf)/sizeof(wchar_t), format, args);
va_end(args);
return buf;
}
};
int stringToInt(const std::string &s);
long stringToLongInt(const std::string &s);
bool isInteger(const char *s);
std::string ToString(const std::wstring &ws);
std::wstring ToWString(const std::string &s);
std::vector<std::string> split(const std::string &s, const std::string &delimiter); std::vector<std::string> split(const std::string &s, const std::string &delimiter);
void replace(std::string &s, const std::string &from, const std::string &to); void replace(std::string &s, const std::string &from, const std::string &to);
@@ -38,6 +73,6 @@ std::string getSharedDirectory(const std::string &dir1, const std::string &dir2)
std::string getEnclosedString(const std::string &s, char a, char b, size_t *pos); std::string getEnclosedString(const std::string &s, char a, char b, size_t *pos);
bool isInteger(const char *s); void removeInvalidCharsFromFilename(std::string &filename);
#endif // _UTILITY_STRING #endif // _UTILITY_STRING

View File

@@ -0,0 +1,157 @@
/***************************************************************************
* Copyright (C) 2008-2012 by Andrzej Rybczak *
* electricityispower@gmail.com *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
#include <cassert>
#include "utility/type_conversions.h"
std::string tagTypeToString(mpd_tag_type tag)
{
switch (tag)
{
case MPD_TAG_ARTIST:
return "Artist";
case MPD_TAG_ALBUM:
return "Album";
case MPD_TAG_ALBUM_ARTIST:
return "Album Artist";
case MPD_TAG_TITLE:
return "Title";
case MPD_TAG_TRACK:
return "Track";
case MPD_TAG_GENRE:
return "Genre";
case MPD_TAG_DATE:
return "Date";
case MPD_TAG_COMPOSER:
return "Composer";
case MPD_TAG_PERFORMER:
return "Performer";
case MPD_TAG_COMMENT:
return "Comment";
case MPD_TAG_DISC:
return "Disc";
default:
return "";
}
}
MPD::MutableSong::SetFunction tagTypeToSetFunction(mpd_tag_type tag)
{
switch (tag)
{
case MPD_TAG_ARTIST:
return &MPD::MutableSong::setArtist;
case MPD_TAG_ALBUM:
return &MPD::MutableSong::setAlbum;
case MPD_TAG_ALBUM_ARTIST:
return &MPD::MutableSong::setAlbumArtist;
case MPD_TAG_TITLE:
return &MPD::MutableSong::setTitle;
case MPD_TAG_TRACK:
return &MPD::MutableSong::setTrack;
case MPD_TAG_GENRE:
return &MPD::MutableSong::setGenre;
case MPD_TAG_DATE:
return &MPD::MutableSong::setDate;
case MPD_TAG_COMPOSER:
return &MPD::MutableSong::setComposer;
case MPD_TAG_PERFORMER:
return &MPD::MutableSong::setPerformer;
case MPD_TAG_COMMENT:
return &MPD::MutableSong::setComment;
case MPD_TAG_DISC:
return &MPD::MutableSong::setDisc;
default:
return 0;
}
}
mpd_tag_type charToTagType(char c)
{
switch (c)
{
case 'a':
return MPD_TAG_ARTIST;
case 'A':
return MPD_TAG_ALBUM_ARTIST;
case 't':
return MPD_TAG_TITLE;
case 'b':
return MPD_TAG_ALBUM;
case 'y':
return MPD_TAG_DATE;
case 'n':
return MPD_TAG_TRACK;
case 'g':
return MPD_TAG_GENRE;
case 'c':
return MPD_TAG_COMPOSER;
case 'p':
return MPD_TAG_PERFORMER;
case 'd':
return MPD_TAG_DISC;
case 'C':
return MPD_TAG_COMMENT;
default:
assert(false);
return MPD_TAG_ARTIST;
}
}
MPD::Song::GetFunction charToGetFunction(char c)
{
switch (c)
{
case 'l':
return &MPD::Song::getLength;
case 'D':
return &MPD::Song::getDirectory;
case 'f':
return &MPD::Song::getName;
case 'a':
return &MPD::Song::getArtist;
case 'A':
return &MPD::Song::getAlbumArtist;
case 't':
return &MPD::Song::getTitle;
case 'b':
return &MPD::Song::getAlbum;
case 'y':
return &MPD::Song::getDate;
case 'n':
return &MPD::Song::getTrackNumber;
case 'N':
return &MPD::Song::getTrack;
case 'g':
return &MPD::Song::getGenre;
case 'c':
return &MPD::Song::getComposer;
case 'p':
return &MPD::Song::getPerformer;
case 'd':
return &MPD::Song::getDisc;
case 'C':
return &MPD::Song::getComment;
case 'P':
return &MPD::Song::getPriority;
default:
return 0;
}
}

View File

@@ -18,43 +18,15 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/ ***************************************************************************/
#ifndef _CONV_H #ifndef _UTILITY_TYPE_CONVERSIONS
#define _CONV_H #define _UTILITY_TYPE_CONVERSIONS
#include <cstring>
#include <string>
#include "numeric_conversions.h"
#include "actions.h"
#include "window.h"
#include "mutable_song.h" #include "mutable_song.h"
#include "song.h"
template <size_t N> inline size_t static_strlen(const char (&)[N]) std::string tagTypeToString(mpd_tag_type tag);
{ MPD::MutableSong::SetFunction tagTypeToSetFunction(mpd_tag_type tag);
return N-1;
}
int StrToInt(const std::string &); mpd_tag_type charToTagType(char c);
long StrToLong(const std::string &); MPD::Song::GetFunction charToGetFunction(char c);
std::string IntoStr(mpd_tag_type);
std::string IntoStr(NCurses::Color);
std::string IntoStr(const Action::Key &key, bool *print_backspace = 0);
NCurses::Color IntoColor(const std::string &);
mpd_tag_type IntoTagItem(char);
MPD::Song::GetFunction toGetFunction(char c);
#ifdef HAVE_TAGLIB_H
MPD::MutableSong::SetFunction IntoSetFunction(mpd_tag_type);
#endif // HAVE_TAGLIB_H
std::string Shorten(const std::basic_string<my_char_t> &s, size_t max_length);
void EscapeUnallowedChars(std::string &);
#endif
#endif // _UTILITY_TYPE_CONVERSIONS

View File

@@ -29,6 +29,7 @@
#endif #endif
#include "error.h" #include "error.h"
#include "utility/string.h"
#include "window.h" #include "window.h"
using namespace NCurses; using namespace NCurses;
@@ -923,31 +924,6 @@ Window &Window::operator<<(size_t s)
return *this; return *this;
} }
std::string ToString(const std::wstring &ws)
{
std::string result;
char s[MB_CUR_MAX];
for (size_t i = 0; i < ws.length(); ++i)
{
int n = wcrtomb(s, ws[i], 0);
if (n > 0)
result.append(s, n);
}
return result;
}
std::wstring ToWString(const std::string &s)
{
std::wstring result;
wchar_t *ws = new wchar_t[s.length()];
const char *c_s = s.c_str();
int n = mbsrtowcs(ws, &c_s, s.length(), 0);
if (n > 0)
result.append(ws, n);
delete [] ws;
return result;
}
size_t Window::Length(const std::wstring &ws) size_t Window::Length(const std::wstring &ws)
{ {
# ifdef WIN32 # ifdef WIN32

View File

@@ -117,18 +117,6 @@
# define wcwidth(x) int(!iscntrl(x)) # define wcwidth(x) int(!iscntrl(x))
#endif #endif
/// Converts wide string to narrow string
/// @param ws wide string
/// @return narrow string
///
std::string ToString(const std::wstring &ws);
/// Converts narrow string to wide string
/// @param s narrow string
/// @return wide string
///
std::wstring ToWString(const std::string &s);
/// NCurses namespace provides set of easy-to-use /// NCurses namespace provides set of easy-to-use
/// wrappers over original curses library /// wrappers over original curses library
/// ///