settings: support customizable tags separator
This commit is contained in:
@@ -1362,7 +1362,7 @@ void EditLibraryTag::Run()
|
||||
for (auto s = songs.begin(); s != songs.end(); ++s)
|
||||
{
|
||||
MPD::MutableSong es = *s;
|
||||
es.setTags(set, new_tag);
|
||||
es.setTags(set, new_tag, Config.tags_separator);
|
||||
Statusbar::msg("Updating tags in \"%s\"...", es.getName().c_str());
|
||||
std::string path = Config.mpd_music_dir + es.getURI();
|
||||
if (!TagEditor::WriteTags(es))
|
||||
|
||||
@@ -616,9 +616,9 @@ std::string ItemToString(const MPD::Item &item)
|
||||
break;
|
||||
case MPD::itSong:
|
||||
if (Config.columns_in_browser)
|
||||
result = item.song->toString(Config.song_in_columns_to_string_format);
|
||||
result = item.song->toString(Config.song_in_columns_to_string_format, Config.tags_separator);
|
||||
else
|
||||
result = item.song->toString(Config.song_list_format_dollar_free);
|
||||
result = item.song->toString(Config.song_list_format_dollar_free, Config.tags_separator);
|
||||
break;
|
||||
case MPD::itPlaylist:
|
||||
result = Config.browser_playlist_prefix.str() + getBasename(item.name);
|
||||
|
||||
@@ -189,7 +189,7 @@ void ParseArgv(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
std::cout << IConv::utf8ToLocale(
|
||||
Mpd.GetCurrentlyPlayingSong().toString(now_playing_format)) << "\n";
|
||||
Mpd.GetCurrentlyPlayingSong().toString(now_playing_format, Config.tags_separator)) << "\n";
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ void showSongs(NC::Menu<T> &menu, const MPD::Song &s, HasSongs &screen, const st
|
||||
setProperties(menu, s, screen, separate_albums, is_now_playing, is_selected, discard_colors);
|
||||
|
||||
size_t y = menu.getY();
|
||||
std::string line = s.toString(format, "$");
|
||||
std::string line = s.toString(format, Config.tags_separator, "$");
|
||||
for (auto it = line.begin(); it != line.end(); ++it)
|
||||
{
|
||||
if (*it == '$')
|
||||
@@ -223,7 +223,7 @@ void showSongsInColumns(NC::Menu<T> &menu, const MPD::Song &s, HasSongs &screen)
|
||||
for (size_t i = 0; i < it->type.length(); ++i)
|
||||
{
|
||||
MPD::Song::GetFunction get = charToGetFunction(it->type[i]);
|
||||
tag = ToWString(get ? s.getTags(get) : "");
|
||||
tag = ToWString(get ? s.getTags(get, Config.tags_separator) : "");
|
||||
if (!tag.empty())
|
||||
break;
|
||||
}
|
||||
@@ -365,7 +365,7 @@ void Display::Tags(NC::Menu<MPD::MutableSong> &menu)
|
||||
size_t i = myTagEditor->TagTypes->choice();
|
||||
if (i < 11)
|
||||
{
|
||||
ShowTag(menu, s.getTags(SongInfo::Tags[i].Get));
|
||||
ShowTag(menu, s.getTags(SongInfo::Tags[i].Get, Config.tags_separator));
|
||||
}
|
||||
else if (i == 12)
|
||||
{
|
||||
|
||||
@@ -152,7 +152,7 @@ void Lyrics::SwitchTo()
|
||||
std::wstring Lyrics::Title()
|
||||
{
|
||||
std::wstring result = L"Lyrics: ";
|
||||
result += Scroller(ToWString(itsSong.toString("{%a - %t}")), itsScrollBegin, COLS-result.length()-(Config.new_design ? 2 : Global::VolumeState.length()));
|
||||
result += Scroller(ToWString(itsSong.toString("{%a - %t}", ", ")), itsScrollBegin, COLS-result.length()-(Config.new_design ? 2 : Global::VolumeState.length()));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -175,7 +175,7 @@ void Lyrics::DownloadInBackground(const MPD::Song &s)
|
||||
f.close();
|
||||
return;
|
||||
}
|
||||
Statusbar::msg("Fetching lyrics for \"%s\"...", s.toString(Config.song_status_format_no_colors).c_str());
|
||||
Statusbar::msg("Fetching lyrics for \"%s\"...", s.toString(Config.song_status_format_no_colors, Config.tags_separator).c_str());
|
||||
|
||||
MPD::Song *s_copy = new MPD::Song(s);
|
||||
pthread_mutex_lock(&itsDIBLock);
|
||||
|
||||
@@ -85,7 +85,8 @@ public:
|
||||
}}), m_cmp(std::locale(), Config.ignore_leading_the) { }
|
||||
bool operator()(const MPD::Song &a, const MPD::Song &b) {
|
||||
for (auto get = m_gets.begin(); get != m_gets.end(); ++get) {
|
||||
int ret = m_cmp(a.getTags(*get), b.getTags(*get));
|
||||
int ret = m_cmp(a.getTags(*get, Config.tags_separator),
|
||||
b.getTags(*get, Config.tags_separator));
|
||||
if (ret != 0)
|
||||
return ret < 0;
|
||||
}
|
||||
@@ -902,7 +903,7 @@ std::string AlbumToString(const SearchConstraints &sc)
|
||||
|
||||
std::string SongToString(const MPD::Song &s)
|
||||
{
|
||||
return s.toString(Config.song_library_format);
|
||||
return s.toString(Config.song_library_format, Config.tags_separator);
|
||||
}
|
||||
|
||||
bool TagEntryMatcher(const Regex &rx, const std::string &tag)
|
||||
|
||||
@@ -63,7 +63,7 @@ struct MutableSong : public Song
|
||||
virtual unsigned getDuration() const;
|
||||
void setDuration(unsigned duration);
|
||||
|
||||
void setTags(SetFunction set, const std::string &value, const std::string &delimiter = "");
|
||||
void setTags(SetFunction set, const std::string &value, const std::string &delimiter);
|
||||
|
||||
bool isModified() const;
|
||||
void clearModifications();
|
||||
|
||||
@@ -203,7 +203,7 @@ void Playlist::EnterPressed()
|
||||
std::function<void(MPD::SongList::iterator, MPD::SongList::iterator)> iter_swap, quick_sort;
|
||||
auto song_cmp = [&cmp](const MPD::Song &a, const MPD::Song &b) -> bool {
|
||||
for (size_t i = 0; i < SortOptions; ++i)
|
||||
if (int ret = cmp(a.getTags((*SortDialog)[i].value().second), b.getTags((*SortDialog)[i].value().second)))
|
||||
if (int ret = cmp(a.getTags((*SortDialog)[i].value().second, Config.tags_separator), b.getTags((*SortDialog)[i].value().second, Config.tags_separator)))
|
||||
return ret < 0;
|
||||
return a.getPosition() < b.getPosition();
|
||||
};
|
||||
@@ -518,7 +518,7 @@ bool Playlist::Add(const MPD::Song &s, bool play, int position)
|
||||
int id = Mpd.AddSong(s, position);
|
||||
if (id >= 0)
|
||||
{
|
||||
Statusbar::msg("Added to playlist: %s", s.toString(Config.song_status_format_no_colors).c_str());
|
||||
Statusbar::msg("Added to playlist: %s", s.toString(Config.song_status_format_no_colors, Config.tags_separator).c_str());
|
||||
if (play)
|
||||
Mpd.PlayID(id);
|
||||
return true;
|
||||
@@ -621,9 +621,9 @@ std::string songToString(const MPD::Song &s)
|
||||
{
|
||||
std::string result;
|
||||
if (Config.columns_in_playlist)
|
||||
result = s.toString(Config.song_in_columns_to_string_format);
|
||||
result = s.toString(Config.song_in_columns_to_string_format, Config.tags_separator);
|
||||
else
|
||||
result = s.toString(Config.song_list_format_dollar_free);
|
||||
result = s.toString(Config.song_list_format_dollar_free, Config.tags_separator);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -521,9 +521,9 @@ std::string SongToString(const MPD::Song &s)
|
||||
{
|
||||
std::string result;
|
||||
if (Config.columns_in_playlist_editor)
|
||||
result = s.toString(Config.song_in_columns_to_string_format);
|
||||
result = s.toString(Config.song_in_columns_to_string_format, Config.tags_separator);
|
||||
else
|
||||
result = s.toString(Config.song_list_format_dollar_free);
|
||||
result = s.toString(Config.song_list_format_dollar_free, Config.tags_separator);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -588,9 +588,9 @@ std::string SEItemToString(const SEItem &ei)
|
||||
if (ei.isSong())
|
||||
{
|
||||
if (Config.columns_in_search_engine)
|
||||
result = ei.song().toString(Config.song_in_columns_to_string_format);
|
||||
result = ei.song().toString(Config.song_in_columns_to_string_format, Config.tags_separator);
|
||||
else
|
||||
result = ei.song().toString(Config.song_list_format_dollar_free);
|
||||
result = ei.song().toString(Config.song_list_format_dollar_free, Config.tags_separator);
|
||||
}
|
||||
else
|
||||
result = ei.buffer().str();
|
||||
|
||||
@@ -161,6 +161,7 @@ void Configuration::SetDefaults()
|
||||
{
|
||||
mpd_host = "localhost";
|
||||
empty_tag = "<empty>";
|
||||
tags_separator = " | ";
|
||||
song_list_columns_format = "(7f)[green]{l} (25)[cyan]{a} (40)[]{t|f} (30)[red]{b}";
|
||||
song_list_format = "{{%a - }{%t}|{$8%f$9}$R{$3(%l)$9}}";
|
||||
song_list_format_dollar_free = RemoveDollarFormatting(song_list_format);
|
||||
@@ -882,6 +883,11 @@ void Configuration::Read()
|
||||
{
|
||||
empty_tag = v; // is this case empty string is allowed
|
||||
}
|
||||
else if (name == "tags_separator")
|
||||
{
|
||||
if (!v.empty())
|
||||
tags_separator = v;
|
||||
}
|
||||
else if (name == "empty_tag_color")
|
||||
{
|
||||
if (!v.empty())
|
||||
|
||||
@@ -64,6 +64,7 @@ struct Configuration
|
||||
std::string visualizer_fifo_path;
|
||||
std::string visualizer_output_name;
|
||||
std::string empty_tag;
|
||||
std::string tags_separator;
|
||||
std::string song_list_columns_format;
|
||||
std::string song_list_format;
|
||||
std::string song_list_format_dollar_free;
|
||||
|
||||
16
src/song.cpp
16
src/song.cpp
@@ -193,7 +193,7 @@ std::string Song::getPriority(unsigned idx) const
|
||||
return unsignedIntTo<std::string>::apply(getPrio());
|
||||
}
|
||||
|
||||
std::string MPD::Song::getTags(GetFunction f, const std::string &tag_separator) const
|
||||
std::string MPD::Song::getTags(GetFunction f, const std::string &tags_separator) const
|
||||
{
|
||||
assert(m_song);
|
||||
unsigned idx = 0;
|
||||
@@ -201,7 +201,7 @@ std::string MPD::Song::getTags(GetFunction f, const std::string &tag_separator)
|
||||
for (std::string tag; !(tag = (this->*f)(idx)).empty(); ++idx)
|
||||
{
|
||||
if (!result.empty())
|
||||
result += tag_separator;
|
||||
result += tags_separator;
|
||||
result += tag;
|
||||
}
|
||||
return result;
|
||||
@@ -261,11 +261,11 @@ bool Song::empty() const
|
||||
return m_song.get() == 0;
|
||||
}
|
||||
|
||||
std::string Song::toString(const std::string &fmt, const std::string &tag_separator, const std::string &escape_chars) const
|
||||
std::string Song::toString(const std::string &fmt, const std::string &tags_separator, const std::string &escape_chars) const
|
||||
{
|
||||
assert(m_song);
|
||||
std::string::const_iterator it = fmt.begin();
|
||||
return ParseFormat(it, tag_separator, escape_chars);
|
||||
return ParseFormat(it, tags_separator, escape_chars);
|
||||
}
|
||||
|
||||
std::string Song::ShowTime(unsigned length)
|
||||
@@ -313,7 +313,7 @@ bool MPD::Song::isFormatOk(const std::string &type, const std::string &fmt)
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Song::ParseFormat(std::string::const_iterator &it, const std::string &tag_separator,
|
||||
std::string Song::ParseFormat(std::string::const_iterator &it, const std::string &tags_separator,
|
||||
const std::string &escape_chars) const
|
||||
{
|
||||
std::string result;
|
||||
@@ -323,7 +323,7 @@ std::string Song::ParseFormat(std::string::const_iterator &it, const std::string
|
||||
{
|
||||
while (*it == '{')
|
||||
{
|
||||
std::string tags = ParseFormat(it, tag_separator, escape_chars);
|
||||
std::string tags = ParseFormat(it, tags_separator, escape_chars);
|
||||
if (!tags.empty())
|
||||
{
|
||||
has_some_tags = 1;
|
||||
@@ -352,7 +352,7 @@ std::string Song::ParseFormat(std::string::const_iterator &it, const std::string
|
||||
|
||||
if (get)
|
||||
{
|
||||
std::string tag = getTags(get, tag_separator);
|
||||
std::string tag = getTags(get, tags_separator);
|
||||
if (!escape_chars.empty()) // prepend format escape character to all given chars to escape
|
||||
{
|
||||
for (size_t i = 0; i < escape_chars.length(); ++i)
|
||||
@@ -384,7 +384,7 @@ std::string Song::ParseFormat(std::string::const_iterator &it, const std::string
|
||||
--brace_counter;
|
||||
}
|
||||
if (*++it == '|')
|
||||
return ParseFormat(++it, tag_separator, escape_chars);
|
||||
return ParseFormat(++it, tags_separator, escape_chars);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ struct Song
|
||||
virtual std::string getLength(unsigned idx = 0) const;
|
||||
virtual std::string getPriority(unsigned idx = 0) const;
|
||||
|
||||
virtual std::string getTags(GetFunction f, const std::string &tag_separator = ", ") const;
|
||||
virtual std::string getTags(GetFunction f, const std::string &tags_separator) const;
|
||||
|
||||
virtual unsigned getHash() const;
|
||||
virtual unsigned getDuration() const;
|
||||
@@ -71,7 +71,7 @@ struct Song
|
||||
|
||||
virtual bool empty() const;
|
||||
|
||||
virtual std::string toString(const std::string &fmt, const std::string &tag_separator = ", ",
|
||||
virtual std::string toString(const std::string &fmt, const std::string &tags_separator,
|
||||
const std::string &escape_chars = "") const;
|
||||
|
||||
static std::string ShowTime(unsigned length);
|
||||
@@ -81,7 +81,7 @@ struct Song
|
||||
|
||||
private:
|
||||
const char *getTag(mpd_tag_type type, unsigned idx) const;
|
||||
std::string ParseFormat(std::string::const_iterator &it, const std::string &tag_separator,
|
||||
std::string ParseFormat(std::string::const_iterator &it, const std::string &tags_separator,
|
||||
const std::string &escape_chars) const;
|
||||
|
||||
std::shared_ptr<mpd_song> m_song;
|
||||
|
||||
@@ -134,6 +134,6 @@ void SongInfo::PrepareSong(MPD::Song &s)
|
||||
for (const Metadata *m = Tags; m->Name; ++m)
|
||||
{
|
||||
*w << NC::fmtBold << '\n' << ToWString(m->Name) << L": " << NC::fmtBoldEnd;
|
||||
ShowTag(*w, s.getTags(m->Get));
|
||||
ShowTag(*w, s.getTags(m->Get, Config.tags_separator));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ char mpd_db_updating;
|
||||
void drawTitle(const MPD::Song &np)
|
||||
{
|
||||
assert(!np.empty());
|
||||
windowTitle(np.toString(Config.song_window_title_format));
|
||||
windowTitle(np.toString(Config.song_window_title_format, Config.tags_separator));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -345,8 +345,8 @@ void Status::Changes::elapsedTime()
|
||||
}
|
||||
|
||||
NC::WBuffer first, second;
|
||||
stringToBuffer(ToWString(IConv::utf8ToLocale(np.toString(Config.new_header_first_line, "$"))), first);
|
||||
stringToBuffer(ToWString(IConv::utf8ToLocale(np.toString(Config.new_header_second_line, "$"))), second);
|
||||
stringToBuffer(ToWString(IConv::utf8ToLocale(np.toString(Config.new_header_first_line, Config.tags_separator, "$"))), first);
|
||||
stringToBuffer(ToWString(IConv::utf8ToLocale(np.toString(Config.new_header_second_line, Config.tags_separator, "$"))), second);
|
||||
|
||||
size_t first_len = wideLength(first.str());
|
||||
size_t first_margin = (std::max(tracklength.length()+1, VolumeState.length()))*2;
|
||||
@@ -397,7 +397,7 @@ void Status::Changes::elapsedTime()
|
||||
tracklength += "]";
|
||||
}
|
||||
NC::WBuffer np_song;
|
||||
stringToBuffer(ToWString(IConv::utf8ToLocale(np.toString(Config.song_status_format, "$"))), np_song);
|
||||
stringToBuffer(ToWString(IConv::utf8ToLocale(np.toString(Config.song_status_format, Config.tags_separator, "$"))), np_song);
|
||||
*wFooter << NC::XY(0, 1) << wclrtoeol << NC::fmtBold << player_state << NC::fmtBoldEnd;
|
||||
np_song.write(*wFooter, playing_song_scroll_begin, wFooter->getWidth()-player_state.length()-tracklength.length(), L" ** ");
|
||||
*wFooter << NC::fmtBold << NC::XY(wFooter->getWidth()-tracklength.length(), 1) << tracklength << NC::fmtBoldEnd;
|
||||
|
||||
@@ -526,19 +526,19 @@ void TagEditor::EnterPressed()
|
||||
{
|
||||
Statusbar::lock();
|
||||
Statusbar::put() << NC::fmtBold << TagTypes->current().value() << NC::fmtBoldEnd << ": ";
|
||||
std::string new_tag = wFooter->getString(Tags->current().value().getTags(get));
|
||||
std::string new_tag = wFooter->getString(Tags->current().value().getTags(get, Config.tags_separator));
|
||||
Statusbar::unlock();
|
||||
for (auto it = EditedSongs.begin(); it != EditedSongs.end(); ++it)
|
||||
(*it)->setTags(set, new_tag);
|
||||
(*it)->setTags(set, new_tag, Config.tags_separator);
|
||||
}
|
||||
else if (w == Tags)
|
||||
{
|
||||
Statusbar::lock();
|
||||
Statusbar::put() << NC::fmtBold << TagTypes->current().value() << NC::fmtBoldEnd << ": ";
|
||||
std::string new_tag = wFooter->getString(Tags->current().value().getTags(get));
|
||||
std::string new_tag = wFooter->getString(Tags->current().value().getTags(get, Config.tags_separator));
|
||||
Statusbar::unlock();
|
||||
if (new_tag != Tags->current().value().getTags(get))
|
||||
Tags->current().value().setTags(set, new_tag);
|
||||
if (new_tag != Tags->current().value().getTags(get, Config.tags_separator))
|
||||
Tags->current().value().setTags(set, new_tag, Config.tags_separator);
|
||||
Tags->scroll(NC::wDown);
|
||||
}
|
||||
}
|
||||
@@ -1254,7 +1254,7 @@ MPD::MutableSong::SetFunction IntoSetFunction(char c)
|
||||
|
||||
std::string GenerateFilename(const MPD::MutableSong &s, const std::string &pattern)
|
||||
{
|
||||
std::string result = s.toString(pattern);
|
||||
std::string result = s.toString(pattern, Config.tags_separator);
|
||||
removeInvalidCharsFromFilename(result);
|
||||
return result;
|
||||
}
|
||||
@@ -1306,7 +1306,7 @@ std::string ParseFilename(MPD::MutableSong &s, std::string mask, bool preview)
|
||||
{
|
||||
MPD::MutableSong::SetFunction set = IntoSetFunction(it->first);
|
||||
if (set)
|
||||
s.setTags(set, it->second);
|
||||
s.setTags(set, it->second, Config.tags_separator);
|
||||
}
|
||||
else
|
||||
result << "%" << it->first << ": " << it->second << "\n";
|
||||
|
||||
@@ -111,10 +111,11 @@ void TinyTagEditor::EnterPressed()
|
||||
{
|
||||
size_t pos = option-8;
|
||||
Statusbar::put() << NC::fmtBold << SongInfo::Tags[pos].Name << ": " << NC::fmtBoldEnd;
|
||||
itsEdited.setTags(SongInfo::Tags[pos].Set, Global::wFooter->getString(itsEdited.getTags(SongInfo::Tags[pos].Get)));
|
||||
itsEdited.setTags(SongInfo::Tags[pos].Set, Global::wFooter->getString(
|
||||
itsEdited.getTags(SongInfo::Tags[pos].Get, Config.tags_separator)), Config.tags_separator);
|
||||
w->at(option).value().clear();
|
||||
w->at(option).value() << NC::fmtBold << SongInfo::Tags[pos].Name << ':' << NC::fmtBoldEnd << ' ';
|
||||
ShowTag(w->at(option).value(), itsEdited.getTags(SongInfo::Tags[pos].Get));
|
||||
ShowTag(w->at(option).value(), itsEdited.getTags(SongInfo::Tags[pos].Get, Config.tags_separator));
|
||||
}
|
||||
else if (option == 20)
|
||||
{
|
||||
@@ -228,7 +229,7 @@ bool TinyTagEditor::getTags()
|
||||
for (const SongInfo::Metadata *m = SongInfo::Tags; m->Name; ++m, ++pos)
|
||||
{
|
||||
w->at(pos).value() << NC::fmtBold << m->Name << ":" << NC::fmtBoldEnd << ' ';
|
||||
ShowTag(w->at(pos).value(), itsEdited.getTags(m->Get));
|
||||
ShowTag(w->at(pos).value(), itsEdited.getTags(m->Get, Config.tags_separator));
|
||||
}
|
||||
|
||||
w->at(20).value() << NC::fmtBold << "Filename:" << NC::fmtBoldEnd << ' ' << itsEdited.getName();
|
||||
|
||||
@@ -74,8 +74,8 @@ bool LocaleBasedItemSorting::operator()(const MPD::Item &a, const MPD::Item &b)
|
||||
result = a.song->getMTime() > b.song->getMTime();
|
||||
break;
|
||||
case smCustomFormat:
|
||||
result = m_cmp(a.song->toString(Config.browser_sort_format),
|
||||
b.song->toString(Config.browser_sort_format));
|
||||
result = m_cmp(a.song->toString(Config.browser_sort_format, Config.tags_separator),
|
||||
b.song->toString(Config.browser_sort_format, Config.tags_separator));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user