add support for multiple tags

This commit is contained in:
Andrzej Rybczak
2009-10-04 21:10:57 +02:00
parent 663aba02d2
commit f61b4716a2
10 changed files with 242 additions and 284 deletions

View File

@@ -186,7 +186,7 @@ void Display::SongsInColumns(const MPD::Song &s, void *, Menu<MPD::Song> *menu)
if (it->color != clDefault) if (it->color != clDefault)
*menu << it->color; *menu << it->color;
whline(menu->Raw(), 32, menu->GetWidth()-where); whline(menu->Raw(), 32, menu->GetWidth()-where);
std::string tag = get ? (s.*get)() : ""; std::string tag = get ? s.GetTags(get) : "";
if (it->right_alignment) if (it->right_alignment)
{ {
if (!tag.empty() || it->display_empty_tag) if (!tag.empty() || it->display_empty_tag)
@@ -267,34 +267,34 @@ void Display::Tags(const MPD::Song &s, void *data, Menu<MPD::Song> *menu)
switch (static_cast<Menu<std::string> *>(data)->Choice()) switch (static_cast<Menu<std::string> *>(data)->Choice())
{ {
case 0: case 0:
ShowTag(*menu, s.GetTitle()); ShowTag(*menu, s.GetTags(&MPD::Song::GetTitle));
return; return;
case 1: case 1:
ShowTag(*menu, s.GetArtist()); ShowTag(*menu, s.GetTags(&MPD::Song::GetArtist));
return; return;
case 2: case 2:
ShowTag(*menu, s.GetAlbum()); ShowTag(*menu, s.GetTags(&MPD::Song::GetAlbum));
return; return;
case 3: case 3:
ShowTag(*menu, s.GetDate()); ShowTag(*menu, s.GetTags(&MPD::Song::GetDate));
return; return;
case 4: case 4:
ShowTag(*menu, s.GetTrack()); ShowTag(*menu, s.GetTags(&MPD::Song::GetTrack));
return; return;
case 5: case 5:
ShowTag(*menu, s.GetGenre()); ShowTag(*menu, s.GetTags(&MPD::Song::GetGenre));
return; return;
case 6: case 6:
ShowTag(*menu, s.GetComposer()); ShowTag(*menu, s.GetTags(&MPD::Song::GetComposer));
return; return;
case 7: case 7:
ShowTag(*menu, s.GetPerformer()); ShowTag(*menu, s.GetTags(&MPD::Song::GetPerformer));
return; return;
case 8: case 8:
ShowTag(*menu, s.GetDisc()); ShowTag(*menu, s.GetTags(&MPD::Song::GetDisc));
return; return;
case 9: case 9:
ShowTag(*menu, s.GetComment()); ShowTag(*menu, s.GetTags(&MPD::Song::GetComment));
return; return;
case 11: case 11:
if (s.GetNewName().empty()) if (s.GetNewName().empty())

View File

@@ -55,6 +55,21 @@ pthread_t *Info::Downloader = 0;
Info *myInfo = new Info; Info *myInfo = new Info;
const Info::Metadata Info::Tags[] =
{
{ "Title", &MPD::Song::GetTitle, &MPD::Song::SetTitle },
{ "Artist", &MPD::Song::GetArtist, &MPD::Song::SetArtist },
{ "Album", &MPD::Song::GetAlbum, &MPD::Song::SetAlbum },
{ "Year", &MPD::Song::GetDate, &MPD::Song::SetDate },
{ "Track", &MPD::Song::GetTrack, &MPD::Song::SetTrack },
{ "Genre", &MPD::Song::GetGenre, &MPD::Song::SetGenre },
{ "Composer", &MPD::Song::GetComposer, &MPD::Song::SetComposer },
{ "Performer", &MPD::Song::GetPerformer, &MPD::Song::SetPerformer },
{ "Disc", &MPD::Song::GetDisc, &MPD::Song::SetDisc },
{ "Comment", &MPD::Song::GetComment, &MPD::Song::SetComment },
{ 0, 0, 0 }
};
void Info::Init() void Info::Init()
{ {
w = new Scrollpad(0, MainStartY, COLS, MainHeight, "", Config.main_color, brNone); w = new Scrollpad(0, MainStartY, COLS, MainHeight, "", Config.main_color, brNone);
@@ -372,25 +387,10 @@ void Info::PrepareSong(MPD::Song &s)
# endif // HAVE_TAGLIB_H # endif // HAVE_TAGLIB_H
*w << clDefault; *w << clDefault;
*w << fmtBold << "\nTitle: " << fmtBoldEnd; for (const Metadata *m = Tags; m->Name; ++m)
ShowTag(*w, s.GetTitle()); {
*w << fmtBold << "\nArtist: " << fmtBoldEnd; *w << fmtBold << "\n" << m->Name << ": " << fmtBoldEnd;
ShowTag(*w, s.GetArtist()); ShowTag(*w, s.GetTags(m->Get));
*w << fmtBold << "\nAlbum: " << fmtBoldEnd; }
ShowTag(*w, s.GetAlbum());
*w << fmtBold << "\nYear: " << fmtBoldEnd;
ShowTag(*w, s.GetDate());
*w << fmtBold << "\nTrack: " << fmtBoldEnd;
ShowTag(*w, s.GetTrack());
*w << fmtBold << "\nGenre: " << fmtBoldEnd;
ShowTag(*w, s.GetGenre());
*w << fmtBold << "\nComposer: " << fmtBoldEnd;
ShowTag(*w, s.GetComposer());
*w << fmtBold << "\nPerformer: " << fmtBoldEnd;
ShowTag(*w, s.GetPerformer());
*w << fmtBold << "\nDisc: " << fmtBoldEnd;
ShowTag(*w, s.GetDisc());
*w << fmtBold << "\nComment: " << fmtBoldEnd;
ShowTag(*w, s.GetComment());
} }

View File

@@ -28,6 +28,13 @@
class Info : public Screen<Scrollpad> class Info : public Screen<Scrollpad>
{ {
public: public:
struct Metadata
{
const char *Name;
MPD::Song::GetFunction Get;
MPD::Song::SetFunction Set;
};
virtual void SwitchTo() { } virtual void SwitchTo() { }
virtual void Resize(); virtual void Resize();
@@ -49,6 +56,8 @@ class Info : public Screen<Scrollpad>
void GetArtist(); void GetArtist();
# endif // HAVE_CURL_CURL_H # endif // HAVE_CURL_CURL_H
static const Metadata Tags[];
protected: protected:
virtual void Init(); virtual void Init();

View File

@@ -1369,7 +1369,7 @@ int main(int argc, char *argv[])
for (SongList::iterator it = list.begin(); it != list.end(); ++it) for (SongList::iterator it = list.begin(); it != list.end(); ++it)
{ {
(*it)->Localize(); (*it)->Localize();
((*it)->*set)(new_tag); (*it)->SetTags(set, new_tag);
ShowMessage("Updating tags in \"%s\"...", (*it)->GetName().c_str()); ShowMessage("Updating tags in \"%s\"...", (*it)->GetName().c_str());
std::string path = Config.mpd_music_dir + (*it)->GetFile(); std::string path = Config.mpd_music_dir + (*it)->GetFile();
if (!TagEditor::WriteTags(**it)) if (!TagEditor::WriteTags(**it))

View File

@@ -323,7 +323,7 @@ bool Playlist::Sorting(MPD::Song *a, MPD::Song *b)
{ {
CaseInsensitiveStringComparison cmp; CaseInsensitiveStringComparison cmp;
for (size_t i = 0; i < SortOptions; ++i) for (size_t i = 0; i < SortOptions; ++i)
if (int ret = cmp((a->*(*SortDialog)[i].second)(), (b->*(*SortDialog)[i].second)())) if (int ret = cmp(a->GetTags((*SortDialog)[i].second), b->GetTags((*SortDialog)[i].second)))
return ret < 0; return ret < 0;
return a->GetPosition() < b->GetPosition(); return a->GetPosition() < b->GetPosition();
} }

View File

@@ -74,8 +74,10 @@ MPD::Song::~Song()
delete itsTags; delete itsTags;
} }
std::string MPD::Song::GetLength() const std::string MPD::Song::GetLength(unsigned pos) const
{ {
if (pos > 0)
return "";
unsigned len = mpd_song_get_duration(itsSong); unsigned len = mpd_song_get_duration(itsSong);
return !len ? "-:--" : ShowTime(len); return !len ? "-:--" : ShowTime(len);
} }
@@ -145,13 +147,15 @@ bool MPD::Song::isStream() const
return !strncmp(MyFilename(), "http://", 7); return !strncmp(MyFilename(), "http://", 7);
} }
std::string MPD::Song::GetFile() const std::string MPD::Song::GetFile(unsigned pos) const
{ {
return MyFilename(); return pos > 0 ? "" : MyFilename();
} }
std::string MPD::Song::GetName() const std::string MPD::Song::GetName(unsigned pos) const
{ {
if (pos > 0)
return "";
std::string name = GetTag(MPD_TAG_NAME, 0); std::string name = GetTag(MPD_TAG_NAME, 0);
if (!name.empty()) if (!name.empty())
return name; return name;
@@ -161,9 +165,9 @@ std::string MPD::Song::GetName() const
return MyFilename(); return MyFilename();
} }
std::string MPD::Song::GetDirectory() const std::string MPD::Song::GetDirectory(unsigned pos) const
{ {
if (isStream()) if (pos > 0 || isStream())
return ""; return "";
else if (itsSlash == std::string::npos) else if (itsSlash == std::string::npos)
return "/"; return "/";
@@ -171,30 +175,30 @@ std::string MPD::Song::GetDirectory() const
return std::string(MyFilename(), itsSlash); return std::string(MyFilename(), itsSlash);
} }
std::string MPD::Song::GetArtist() const std::string MPD::Song::GetArtist(unsigned pos) const
{ {
return GetTag(MPD_TAG_ARTIST, 0); return GetTag(MPD_TAG_ARTIST, pos);
} }
std::string MPD::Song::GetTitle() const std::string MPD::Song::GetTitle(unsigned pos) const
{ {
return GetTag(MPD_TAG_TITLE, 0); return GetTag(MPD_TAG_TITLE, pos);
} }
std::string MPD::Song::GetAlbum() const std::string MPD::Song::GetAlbum(unsigned pos) const
{ {
return GetTag(MPD_TAG_ALBUM, 0); return GetTag(MPD_TAG_ALBUM, pos);
} }
std::string MPD::Song::GetTrack() const std::string MPD::Song::GetTrack(unsigned pos) const
{ {
std::string track = GetTag(MPD_TAG_TRACK, 0); std::string track = GetTag(MPD_TAG_TRACK, pos);
return track.length() == 1 && track[0] != '0' ? "0"+track : track; return track.length() == 1 && track[0] != '0' ? "0"+track : track;
} }
std::string MPD::Song::GetTrackNumber() const std::string MPD::Song::GetTrackNumber(unsigned pos) const
{ {
std::string track = GetTag(MPD_TAG_TRACK, 0); std::string track = GetTag(MPD_TAG_TRACK, pos);
size_t slash = track.find('/'); size_t slash = track.find('/');
if (slash != std::string::npos) if (slash != std::string::npos)
{ {
@@ -205,94 +209,107 @@ std::string MPD::Song::GetTrackNumber() const
return track; return track;
} }
std::string MPD::Song::GetDate() const std::string MPD::Song::GetDate(unsigned pos) const
{ {
return GetTag(MPD_TAG_DATE, 0); return GetTag(MPD_TAG_DATE, pos);
} }
std::string MPD::Song::GetGenre() const std::string MPD::Song::GetGenre(unsigned pos) const
{ {
return GetTag(MPD_TAG_GENRE, 0); return GetTag(MPD_TAG_GENRE, pos);
} }
std::string MPD::Song::GetComposer() const std::string MPD::Song::GetComposer(unsigned pos) const
{ {
return GetTag(MPD_TAG_COMPOSER, 0); return GetTag(MPD_TAG_COMPOSER, pos);
} }
std::string MPD::Song::GetPerformer() const std::string MPD::Song::GetPerformer(unsigned pos) const
{ {
return GetTag(MPD_TAG_PERFORMER, 0); return GetTag(MPD_TAG_PERFORMER, pos);
} }
std::string MPD::Song::GetDisc() const std::string MPD::Song::GetDisc(unsigned pos) const
{ {
return GetTag(MPD_TAG_DISC, 0); return GetTag(MPD_TAG_DISC, pos);
} }
std::string MPD::Song::GetComment() const std::string MPD::Song::GetComment(unsigned pos) const
{ {
return GetTag(MPD_TAG_COMMENT, 0); return GetTag(MPD_TAG_COMMENT, pos);
} }
void MPD::Song::SetArtist(const std::string &str) std::string MPD::Song::GetTags(GetFunction f) const
{ {
SetTag(MPD_TAG_ARTIST, 0, str); unsigned pos = 0;
std::string result;
for (std::string tag; !(tag = (this->*f)(pos)).empty(); ++pos)
{
if (!result.empty())
result += ", ";
result += tag;
}
return result;
} }
void MPD::Song::SetTitle(const std::string &str) void MPD::Song::SetArtist(const std::string &str, unsigned pos)
{ {
SetTag(MPD_TAG_TITLE, 0, str); SetTag(MPD_TAG_ARTIST, pos, str);
} }
void MPD::Song::SetAlbum(const std::string &str) void MPD::Song::SetTitle(const std::string &str, unsigned pos)
{ {
SetTag(MPD_TAG_ALBUM, 0, str); SetTag(MPD_TAG_TITLE, pos, str);
} }
void MPD::Song::SetTrack(const std::string &str) void MPD::Song::SetAlbum(const std::string &str, unsigned pos)
{ {
SetTag(MPD_TAG_TRACK, 0, str); SetTag(MPD_TAG_ALBUM, pos, str);
} }
void MPD::Song::SetTrack(unsigned track) void MPD::Song::SetTrack(const std::string &str, unsigned pos)
{ {
SetTag(MPD_TAG_ARTIST, 0, IntoStr(track)); SetTag(MPD_TAG_TRACK, pos, str);
} }
void MPD::Song::SetDate(const std::string &str) void MPD::Song::SetTrack(unsigned track, unsigned pos)
{ {
SetTag(MPD_TAG_DATE, 0, str); SetTag(MPD_TAG_ARTIST, pos, IntoStr(track));
} }
void MPD::Song::SetDate(unsigned year) void MPD::Song::SetDate(const std::string &str, unsigned pos)
{ {
SetTag(MPD_TAG_TRACK, 0, IntoStr(year)); SetTag(MPD_TAG_DATE, pos, str);
} }
void MPD::Song::SetGenre(const std::string &str) void MPD::Song::SetDate(unsigned year, unsigned pos)
{ {
SetTag(MPD_TAG_GENRE, 0, str); SetTag(MPD_TAG_TRACK, pos, IntoStr(year));
} }
void MPD::Song::SetComposer(const std::string &str) void MPD::Song::SetGenre(const std::string &str, unsigned pos)
{ {
SetTag(MPD_TAG_COMPOSER, 0, str); SetTag(MPD_TAG_GENRE, pos, str);
} }
void MPD::Song::SetPerformer(const std::string &str) void MPD::Song::SetComposer(const std::string &str, unsigned pos)
{ {
SetTag(MPD_TAG_PERFORMER, 0, str); SetTag(MPD_TAG_COMPOSER, pos, str);
} }
void MPD::Song::SetDisc(const std::string &str) void MPD::Song::SetPerformer(const std::string &str, unsigned pos)
{ {
SetTag(MPD_TAG_DISC, 0, str); SetTag(MPD_TAG_PERFORMER, pos, str);
} }
void MPD::Song::SetComment(const std::string &str) void MPD::Song::SetDisc(const std::string &str, unsigned pos)
{ {
SetTag(MPD_TAG_COMMENT, 0, str); SetTag(MPD_TAG_DISC, pos, str);
}
void MPD::Song::SetComment(const std::string &str, unsigned pos)
{
SetTag(MPD_TAG_COMMENT, pos, str);
} }
void MPD::Song::SetPosition(unsigned pos) void MPD::Song::SetPosition(unsigned pos)
@@ -300,6 +317,32 @@ void MPD::Song::SetPosition(unsigned pos)
mpd_song_set_pos(itsSong, pos); mpd_song_set_pos(itsSong, pos);
} }
void MPD::Song::SetTags(SetFunction f, const std::string &value)
{
unsigned pos = 0;
// tag editor can save multiple instances of performer and composer
// tag, so we need to split them and allow it to read them separately.
if (f == &Song::SetComposer || f == &Song::SetPerformer)
{
for (size_t i = 0; i != std::string::npos; i = value.find(",", i))
{
if (i)
++i;
while (value[i] == ' ')
++i;
size_t j = value.find(",", i);
(this->*f)(value.substr(i, j-i), pos++);
}
}
else
(this->*f)(value, pos++);
// there should be empty tag at the end since if we are
// reading them, original tag from mpd_song at the position
// after the last one locally set can be non-empty and in this
// case GetTags() would read it, which is undesirable.
(this->*f)("", pos);
}
std::string MPD::Song::ParseFormat(std::string::const_iterator &it, const char *escape_chars) const std::string MPD::Song::ParseFormat(std::string::const_iterator &it, const char *escape_chars) const
{ {
std::string result; std::string result;
@@ -373,7 +416,7 @@ std::string MPD::Song::ParseFormat(std::string::const_iterator &it, const char *
} }
if (get) if (get)
{ {
std::string tag = (this->*get)(); std::string tag = GetTags(get);
if (escape_chars) // prepend format escape character to all given chars to escape if (escape_chars) // prepend format escape character to all given chars to escape
for (const char *ch = escape_chars; *ch; ++ch) for (const char *ch = escape_chars; *ch; ++ch)
for (size_t i = tag.find(*ch); i != std::string::npos; i = tag.find(*ch, i += 2)) for (size_t i = tag.find(*ch); i != std::string::npos; i = tag.find(*ch, i += 2))

View File

@@ -34,48 +34,52 @@ namespace MPD
public: public:
typedef void (Song::*SetFunction)(const std::string &); typedef void (Song::*SetFunction)(const std::string &, unsigned);
typedef std::string (Song::*GetFunction)() const; typedef std::string (Song::*GetFunction)(unsigned) const;
Song(mpd_song * = 0, bool = 0); Song(mpd_song * = 0, bool = 0);
Song(const Song &); Song(const Song &);
~Song(); ~Song();
std::string GetFile() const; std::string GetFile(unsigned = 0) const;
std::string GetName() const; std::string GetName(unsigned = 0) const;
std::string GetDirectory() const; std::string GetDirectory(unsigned = 0) const;
std::string GetArtist() const; std::string GetArtist(unsigned = 0) const;
std::string GetTitle() const; std::string GetTitle(unsigned = 0) const;
std::string GetAlbum() const; std::string GetAlbum(unsigned = 0) const;
std::string GetTrack() const; std::string GetTrack(unsigned = 0) const;
std::string GetTrackNumber() const; std::string GetTrackNumber(unsigned = 0) const;
std::string GetDate() const; std::string GetDate(unsigned = 0) const;
std::string GetGenre() const; std::string GetGenre(unsigned = 0) const;
std::string GetComposer() const; std::string GetComposer(unsigned = 0) const;
std::string GetPerformer() const; std::string GetPerformer(unsigned = 0) const;
std::string GetDisc() const; std::string GetDisc(unsigned = 0) const;
std::string GetComment() const; std::string GetComment(unsigned = 0) const;
std::string GetLength() const; std::string GetLength(unsigned = 0) const;
std::string GetTags(GetFunction) const;
unsigned GetHash() const { return itsHash; } unsigned GetHash() const { return itsHash; }
unsigned GetTotalLength() const { return mpd_song_get_duration(itsSong); } unsigned GetTotalLength() const { return mpd_song_get_duration(itsSong); }
unsigned GetPosition() const { return mpd_song_get_pos(itsSong); } unsigned GetPosition() const { return mpd_song_get_pos(itsSong); }
unsigned GetID() const { return mpd_song_get_id(itsSong); } unsigned GetID() const { return mpd_song_get_id(itsSong); }
void SetArtist(const std::string &); void SetArtist(const std::string &, unsigned = 0);
void SetTitle(const std::string &); void SetTitle(const std::string &, unsigned = 0);
void SetAlbum(const std::string &); void SetAlbum(const std::string &, unsigned = 0);
void SetTrack(const std::string &); void SetTrack(const std::string &, unsigned = 0);
void SetTrack(unsigned); void SetTrack(unsigned, unsigned = 0);
void SetDate(const std::string &); void SetDate(const std::string &, unsigned = 0);
void SetDate(unsigned); void SetDate(unsigned, unsigned = 0);
void SetGenre(const std::string &); void SetGenre(const std::string &, unsigned = 0);
void SetComposer(const std::string &); void SetComposer(const std::string &, unsigned = 0);
void SetPerformer(const std::string &); void SetPerformer(const std::string &, unsigned = 0);
void SetDisc(const std::string &); void SetDisc(const std::string &, unsigned = 0);
void SetComment(const std::string &); void SetComment(const std::string &, unsigned = 0);
void SetPosition(unsigned); void SetPosition(unsigned);
void SetTags(SetFunction, const std::string &);
void SetNewName(const std::string &name) { itsNewName = name == GetName() ? "" : name; } void SetNewName(const std::string &name) { itsNewName = name == GetName() ? "" : name; }
std::string GetNewName() const { return itsNewName; } std::string GetNewName() const { return itsNewName; }

View File

@@ -664,19 +664,19 @@ void TagEditor::EnterPressed()
{ {
LockStatusbar(); LockStatusbar();
Statusbar() << fmtBold << TagTypes->Current() << fmtBoldEnd << ": "; Statusbar() << fmtBold << TagTypes->Current() << fmtBoldEnd << ": ";
std::string new_tag = wFooter->GetString((Tags->Current().*get)()); std::string new_tag = wFooter->GetString(Tags->Current().GetTags(get));
UnlockStatusbar(); UnlockStatusbar();
for (MPD::SongList::iterator it = EditedSongs.begin(); it != EditedSongs.end(); ++it) for (MPD::SongList::iterator it = EditedSongs.begin(); it != EditedSongs.end(); ++it)
(**it.*set)(new_tag); (*it)->SetTags(set, new_tag);
} }
else if (w == Tags && set) else if (w == Tags && set)
{ {
LockStatusbar(); LockStatusbar();
Statusbar() << fmtBold << TagTypes->Current() << fmtBoldEnd << ": "; Statusbar() << fmtBold << TagTypes->Current() << fmtBoldEnd << ": ";
std::string new_tag = wFooter->GetString((Tags->Current().*get)()); std::string new_tag = wFooter->GetString(Tags->Current().GetTags(get));
UnlockStatusbar(); UnlockStatusbar();
if (new_tag != (Tags->Current().*get)()) if (new_tag != Tags->Current().GetTags(get))
(Tags->Current().*set)(new_tag); Tags->Current().SetTags(set, new_tag);
Tags->Scroll(wDown); Tags->Scroll(wDown);
} }
} }
@@ -918,12 +918,12 @@ void TagEditor::WriteXiphComments(const MPD::Song &s, TagLib::Ogg::XiphComment *
tag->addField("DISCNUMBER", ToWString(s.GetDisc())); // disc tag->addField("DISCNUMBER", ToWString(s.GetDisc())); // disc
tag->removeField("COMPOSER"); // composer tag->removeField("COMPOSER"); // composer
GetTagList(list, s.GetComposer()); GetTagList(list, s, &MPD::Song::GetComposer);
for (TagLib::StringList::ConstIterator it = list.begin(); it != list.end(); ++it) for (TagLib::StringList::ConstIterator it = list.begin(); it != list.end(); ++it)
tag->addField("COMPOSER", *it, 0); tag->addField("COMPOSER", *it, 0);
tag->removeField("PERFORMER"); // performer tag->removeField("PERFORMER"); // performer
GetTagList(list, s.GetPerformer()); GetTagList(list, s, &MPD::Song::GetPerformer);
for (TagLib::StringList::ConstIterator it = list.begin(); it != list.end(); ++it) for (TagLib::StringList::ConstIterator it = list.begin(); it != list.end(); ++it)
tag->addField("PERFORMER", *it, 0); tag->addField("PERFORMER", *it, 0);
} }
@@ -959,10 +959,10 @@ bool TagEditor::WriteTags(MPD::Song &s)
WriteID3v2("TCON", tag, ToWString(s.GetGenre())); // genre WriteID3v2("TCON", tag, ToWString(s.GetGenre())); // genre
WriteID3v2("TPOS", tag, ToWString(s.GetDisc())); // disc WriteID3v2("TPOS", tag, ToWString(s.GetDisc())); // disc
GetTagList(list, s.GetComposer()); GetTagList(list, s, &MPD::Song::GetComposer);
WriteID3v2("TCOM", tag, list); // composer WriteID3v2("TCOM", tag, list); // composer
GetTagList(list, s.GetPerformer()); GetTagList(list, s, &MPD::Song::GetPerformer);
// in >=mpd-0.16 treating TOPE frame as performer tag // in >=mpd-0.16 treating TOPE frame as performer tag
// was dropped in favor of TPE3/TPE4 frames, so we have // was dropped in favor of TPE3/TPE4 frames, so we have
// to write frame accurate to used mpd version // to write frame accurate to used mpd version
@@ -1075,18 +1075,12 @@ void TagEditor::LowerAllLetters(MPD::Song &s)
s.SetComment(conv); s.SetComment(conv);
} }
void TagEditor::GetTagList(TagLib::StringList &list, const std::string &s) void TagEditor::GetTagList(TagLib::StringList &list, const MPD::Song &s, MPD::Song::GetFunction f)
{ {
list.clear(); list.clear();
for (size_t i = 0; i != std::string::npos; i = s.find(",", i)) unsigned pos = 0;
{ for (std::string value; !(value = (s.*f)(pos)).empty(); ++pos)
if (i) list.append(ToWString(value));
++i;
while (s[i] == ' ')
++i;
size_t j = s.find(",", i);
list.append(ToWString(s.substr(i, j-i)));
}
} }
std::string TagEditor::TagToString(const MPD::Song &s, void *data) std::string TagEditor::TagToString(const MPD::Song &s, void *data)
@@ -1244,7 +1238,7 @@ std::string TagEditor::ParseFilename(MPD::Song &s, std::string mask, bool previe
{ {
MPD::Song::SetFunction set = IntoSetFunction(it->first); MPD::Song::SetFunction set = IntoSetFunction(it->first);
if (set) if (set)
(s.*set)(it->second); s.SetTags(set, it->second);
} }
else else
result << "%" << it->first << ": " << it->second << "\n"; result << "%" << it->first << ": " << it->second << "\n";

View File

@@ -96,7 +96,7 @@ class TagEditor : public Screen<Window>
static std::string CapitalizeFirstLetters(const std::string &); static std::string CapitalizeFirstLetters(const std::string &);
static void CapitalizeFirstLetters(MPD::Song &); static void CapitalizeFirstLetters(MPD::Song &);
static void LowerAllLetters(MPD::Song &); static void LowerAllLetters(MPD::Song &);
static void GetTagList(TagLib::StringList &, const std::string &); static void GetTagList(TagLib::StringList &, const MPD::Song &, MPD::Song::GetFunction);
static void WriteXiphComments(const MPD::Song &, TagLib::Ogg::XiphComment *); static void WriteXiphComments(const MPD::Song &, TagLib::Ogg::XiphComment *);
static void GetPatternList(); static void GetPatternList();

View File

@@ -31,6 +31,7 @@
#include "charset.h" #include "charset.h"
#include "display.h" #include "display.h"
#include "global.h" #include "global.h"
#include "info.h"
#include "playlist.h" #include "playlist.h"
#include "search_engine.h" #include "search_engine.h"
#include "tag_editor.h" #include "tag_editor.h"
@@ -93,137 +94,58 @@ std::basic_string<my_char_t> TinyTagEditor::Title()
void TinyTagEditor::EnterPressed() void TinyTagEditor::EnterPressed()
{ {
size_t option = w->Choice(); size_t option = w->Choice();
LockStatusbar();
if (option >= 8 && option <= 20)
w->at(option).Clear();
MPD::Song &s = itsEdited; MPD::Song &s = itsEdited;
switch (option-7) if (option < 20) // separator after filename
w->at(option).Clear();
LockStatusbar();
if (option < 17) // separator after comment
{ {
case 1: size_t pos = option-8;
{ Statusbar() << fmtBold << Info::Tags[pos].Name << ": " << fmtBoldEnd;
Statusbar() << fmtBold << "Title: " << fmtBoldEnd; s.SetTags(Info::Tags[pos].Set, wFooter->GetString(s.GetTags(Info::Tags[pos].Get)));
s.SetTitle(wFooter->GetString(s.GetTitle())); w->at(option) << fmtBold << Info::Tags[pos].Name << ':' << fmtBoldEnd << ' ';
w->at(option) << fmtBold << "Title:" << fmtBoldEnd << ' '; ShowTag(w->at(option), s.GetTags(Info::Tags[pos].Get));
ShowTag(w->at(option), s.GetTitle()); }
break; else if (option == 19)
} {
case 2: Statusbar() << fmtBold << "Filename: " << fmtBoldEnd;
{ std::string filename = s.GetNewName().empty() ? s.GetName() : s.GetNewName();
Statusbar() << fmtBold << "Artist: " << fmtBoldEnd; size_t dot = filename.rfind(".");
s.SetArtist(wFooter->GetString(s.GetArtist())); std::string extension = filename.substr(dot);
w->at(option) << fmtBold << "Artist:" << fmtBoldEnd << ' '; filename = filename.substr(0, dot);
ShowTag(w->at(option), s.GetArtist()); std::string new_name = wFooter->GetString(filename);
break; s.SetNewName(new_name + extension);
} w->at(option) << fmtBold << "Filename:" << fmtBoldEnd << ' ' << (s.GetNewName().empty() ? s.GetName() : s.GetNewName());
case 3:
{
Statusbar() << fmtBold << "Album: " << fmtBoldEnd;
s.SetAlbum(wFooter->GetString(s.GetAlbum()));
w->at(option) << fmtBold << "Album:" << fmtBoldEnd << ' ';
ShowTag(w->at(option), s.GetAlbum());
break;
}
case 4:
{
Statusbar() << fmtBold << "Year: " << fmtBoldEnd;
s.SetDate(wFooter->GetString(s.GetDate()));
w->at(option) << fmtBold << "Year:" << fmtBoldEnd << ' ';
ShowTag(w->at(option), s.GetDate());
break;
}
case 5:
{
Statusbar() << fmtBold << "Track: " << fmtBoldEnd;
s.SetTrack(wFooter->GetString(s.GetTrack()));
w->at(option) << fmtBold << "Track:" << fmtBoldEnd << ' ';
ShowTag(w->at(option), s.GetTrack());
break;
}
case 6:
{
Statusbar() << fmtBold << "Genre: " << fmtBoldEnd;
s.SetGenre(wFooter->GetString(s.GetGenre()));
w->at(option) << fmtBold << "Genre:" << fmtBoldEnd << ' ';
ShowTag(w->at(option), s.GetGenre());
break;
}
case 7:
{
Statusbar() << fmtBold << "Composer: " << fmtBoldEnd;
s.SetComposer(wFooter->GetString(s.GetComposer()));
w->at(option) << fmtBold << "Composer:" << fmtBoldEnd << ' ';
ShowTag(w->at(option), s.GetComposer());
break;
}
case 8:
{
Statusbar() << fmtBold << "Performer: " << fmtBoldEnd;
s.SetPerformer(wFooter->GetString(s.GetPerformer()));
w->at(option) << fmtBold << "Performer:" << fmtBoldEnd << ' ';
ShowTag(w->at(option), s.GetPerformer());
break;
}
case 9:
{
Statusbar() << fmtBold << "Disc: " << fmtBoldEnd;
s.SetDisc(wFooter->GetString(s.GetDisc()));
w->at(option) << fmtBold << "Disc:" << fmtBoldEnd << ' ';
ShowTag(w->at(option), s.GetDisc());
break;
}
case 10:
{
Statusbar() << fmtBold << "Comment: " << fmtBoldEnd;
s.SetComment(wFooter->GetString(s.GetComment()));
w->at(option) << fmtBold << "Comment:" << fmtBoldEnd << ' ';
ShowTag(w->at(option), s.GetComment());
break;
}
case 12:
{
Statusbar() << fmtBold << "Filename: " << fmtBoldEnd;
std::string filename = s.GetNewName().empty() ? s.GetName() : s.GetNewName();
size_t dot = filename.rfind(".");
std::string extension = filename.substr(dot);
filename = filename.substr(0, dot);
std::string new_name = wFooter->GetString(filename);
s.SetNewName(new_name + extension);
w->at(option) << fmtBold << "Filename:" << fmtBoldEnd << ' ' << (s.GetNewName().empty() ? s.GetName() : s.GetNewName());
break;
}
case 14:
{
ShowMessage("Updating tags...");
if (TagEditor::WriteTags(s))
{
ShowMessage("Tags updated!");
if (s.isFromDB())
{
Mpd.UpdateDirectory(locale_to_utf_cpy(s.GetDirectory()));
if (myOldScreen == mySearcher) // songs from search engine are not updated automatically
*mySearcher->Main()->Current().second = s;
}
else
{
if (myOldScreen == myPlaylist)
myPlaylist->Items->Current() = s;
else if (myOldScreen == myBrowser)
*myBrowser->Main()->Current().song = s;
}
}
else
ShowMessage("Error writing tags!");
}
case 15:
{
myOldScreen->SwitchTo();
break;
}
} }
UnlockStatusbar(); UnlockStatusbar();
if (option == 21)
{
ShowMessage("Updating tags...");
if (TagEditor::WriteTags(s))
{
ShowMessage("Tags updated!");
if (s.isFromDB())
{
Mpd.UpdateDirectory(locale_to_utf_cpy(s.GetDirectory()));
if (myOldScreen == mySearcher) // songs from search engine are not updated automatically
*mySearcher->Main()->Current().second = s;
}
else
{
if (myOldScreen == myPlaylist)
myPlaylist->Items->Current() = s;
else if (myOldScreen == myBrowser)
*myBrowser->Main()->Current().song = s;
}
}
else
ShowMessage("Error writing tags!");
}
if (option > 20)
myOldScreen->SwitchTo();
} }
void TinyTagEditor::MouseButtonPressed(MEVENT me) void TinyTagEditor::MouseButtonPressed(MEVENT me)
@@ -301,29 +223,15 @@ bool TinyTagEditor::GetTags()
w->at(5) << fmtBold << Config.color1 << "Sample rate: " << fmtBoldEnd << Config.color2 << f.audioProperties()->sampleRate() << " Hz" << clEnd; w->at(5) << fmtBold << Config.color1 << "Sample rate: " << fmtBoldEnd << Config.color2 << f.audioProperties()->sampleRate() << " Hz" << clEnd;
w->at(6) << fmtBold << Config.color1 << "Channels: " << fmtBoldEnd << Config.color2 << (f.audioProperties()->channels() == 1 ? "Mono" : "Stereo") << clDefault; w->at(6) << fmtBold << Config.color1 << "Channels: " << fmtBoldEnd << Config.color2 << (f.audioProperties()->channels() == 1 ? "Mono" : "Stereo") << clDefault;
w->at(8) << fmtBold << "Title:" << fmtBoldEnd << ' '; unsigned pos = 8;
ShowTag(w->at(8), s.GetTitle()); for (const Info::Metadata *m = Info::Tags; m->Name; ++m, ++pos)
w->at(9) << fmtBold << "Artist:" << fmtBoldEnd << ' '; {
ShowTag(w->at(9), s.GetArtist()); w->at(pos) << fmtBold << m->Name << ":" << fmtBoldEnd << ' ';
w->at(10) << fmtBold << "Album:" << fmtBoldEnd << ' '; ShowTag(w->at(pos), s.GetTags(m->Get));
ShowTag(w->at(10), s.GetAlbum()); }
w->at(11) << fmtBold << "Year:" << fmtBoldEnd << ' ';
ShowTag(w->at(11), s.GetDate());
w->at(12) << fmtBold << "Track:" << fmtBoldEnd << ' ';
ShowTag(w->at(12), s.GetTrack());
w->at(13) << fmtBold << "Genre:" << fmtBoldEnd << ' ';
ShowTag(w->at(13), s.GetGenre());
w->at(14) << fmtBold << "Composer:" << fmtBoldEnd << ' ';
ShowTag(w->at(14), s.GetComposer());
w->at(15) << fmtBold << "Performer:" << fmtBoldEnd << ' ';
ShowTag(w->at(15), s.GetPerformer());
w->at(16) << fmtBold << "Disc:" << fmtBoldEnd << ' ';
ShowTag(w->at(16), s.GetDisc());
w->at(17) << fmtBold << "Comment:" << fmtBoldEnd << ' ';
ShowTag(w->at(17), s.GetComment());
w->at(19) << fmtBold << "Filename:" << fmtBoldEnd << ' ' << s.GetName(); w->at(19) << fmtBold << "Filename:" << fmtBoldEnd << ' ' << s.GetName();
w->at(21) << "Save"; w->at(21) << "Save";
w->at(22) << "Cancel"; w->at(22) << "Cancel";
return true; return true;