fixes for db97a1a3186b2bbd9d36770e83aa5325db5ce77a
[ncmpcpp.git] / src / tiny_tag_editor.cpp
blob8ef79c40b4ddc12f894a3a2fa0d2ba9b4f4618b7
1 /***************************************************************************
2 * Copyright (C) 2008-2010 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
21 #include "tiny_tag_editor.h"
23 #ifdef HAVE_TAGLIB_H
25 // taglib includes
26 #include "mpegfile.h"
27 #include "vorbisfile.h"
28 #include "flacfile.h"
30 #include "browser.h"
31 #include "charset.h"
32 #include "display.h"
33 #include "global.h"
34 #include "info.h"
35 #include "playlist.h"
36 #include "search_engine.h"
37 #include "tag_editor.h"
39 using Global::MainHeight;
40 using Global::MainStartY;
41 using Global::myOldScreen;
43 TinyTagEditor *myTinyTagEditor = new TinyTagEditor;
45 void TinyTagEditor::Init()
47 w = new Menu<Buffer>(0, MainStartY, COLS, MainHeight, "", Config.main_color, brNone);
48 w->HighlightColor(Config.main_highlight_color);
49 w->CyclicScrolling(Config.use_cyclic_scrolling);
50 w->SetItemDisplayer(Display::Generic);
51 isInitialized = 1;
54 void TinyTagEditor::Resize()
56 w->Resize(COLS, MainHeight);
57 w->MoveTo(0, MainStartY);
58 hasToBeResized = 0;
61 void TinyTagEditor::SwitchTo()
63 if (itsEdited.isStream())
65 ShowMessage("Streams cannot be edited!");
67 else if (GetTags())
69 if (hasToBeResized)
70 Resize();
71 myOldScreen = Global::myScreen;
72 Global::myScreen = this;
73 Global::RedrawHeader = 1;
75 else
77 std::string full_path;
78 if (itsEdited.isFromDB())
79 full_path += Config.mpd_music_dir;
80 full_path += itsEdited.GetFile();
82 std::string message = "Couldn't read file \"";
83 message += Shorten(TO_WSTRING(full_path), COLS-message.length()-3);
84 message += "\"!";
85 ShowMessage("%s", message.c_str());
89 std::basic_string<my_char_t> TinyTagEditor::Title()
91 return U("Tiny tag editor");
94 void TinyTagEditor::EnterPressed()
96 size_t option = w->Choice();
97 MPD::Song &s = itsEdited;
99 LockStatusbar();
100 if (option < 19) // separator after comment
102 size_t pos = option-8;
103 Statusbar() << fmtBold << Info::Tags[pos].Name << ": " << fmtBoldEnd;
104 s.SetTags(Info::Tags[pos].Set, Global::wFooter->GetString(s.GetTags(Info::Tags[pos].Get)));
105 w->at(option).Clear();
106 w->at(option) << fmtBold << Info::Tags[pos].Name << ':' << fmtBoldEnd << ' ';
107 ShowTag(w->at(option), s.GetTags(Info::Tags[pos].Get));
109 else if (option == 20)
111 Statusbar() << fmtBold << "Filename: " << fmtBoldEnd;
112 std::string filename = s.GetNewName().empty() ? s.GetName() : s.GetNewName();
113 size_t dot = filename.rfind(".");
114 std::string extension = filename.substr(dot);
115 filename = filename.substr(0, dot);
116 std::string new_name = Global::wFooter->GetString(filename);
117 s.SetNewName(new_name + extension);
118 w->at(option).Clear();
119 w->at(option) << fmtBold << "Filename:" << fmtBoldEnd << ' ' << (s.GetNewName().empty() ? s.GetName() : s.GetNewName());
121 UnlockStatusbar();
123 if (option == 22)
125 ShowMessage("Updating tags...");
126 if (TagEditor::WriteTags(s))
128 ShowMessage("Tags updated!");
129 if (s.isFromDB())
131 Mpd.UpdateDirectory(locale_to_utf_cpy(s.GetDirectory()));
132 if (myOldScreen == mySearcher) // songs from search engine are not updated automatically
133 *mySearcher->Main()->Current().second = s;
135 else
137 if (myOldScreen == myPlaylist)
138 myPlaylist->Items->Current() = s;
139 else if (myOldScreen == myBrowser)
140 myBrowser->GetDirectory(myBrowser->CurrentDir());
143 else
144 ShowMessage("Error while writing tags!");
146 if (option > 21)
147 myOldScreen->SwitchTo();
150 void TinyTagEditor::MouseButtonPressed(MEVENT me)
152 if (w->Empty() || !w->hasCoords(me.x, me.y) || size_t(me.y) >= w->Size())
153 return;
154 if (me.bstate & (BUTTON1_PRESSED | BUTTON3_PRESSED))
156 if (!w->Goto(me.y))
157 return;
158 if (me.bstate & BUTTON3_PRESSED)
160 w->Refresh();
161 EnterPressed();
164 else
165 Screen< Menu<Buffer> >::MouseButtonPressed(me);
168 bool TinyTagEditor::SetEdited(MPD::Song *s)
170 if (!s)
171 return false;
172 itsEdited = *s;
173 return true;
176 bool TinyTagEditor::GetTags()
178 MPD::Song &s = itsEdited;
180 std::string path_to_file;
181 if (s.isFromDB())
182 path_to_file += Config.mpd_music_dir;
183 path_to_file += s.GetFile();
184 locale_to_utf(path_to_file);
186 TagLib::FileRef f(path_to_file.c_str());
187 if (f.isNull())
188 return false;
189 s.SetComment(f.tag()->comment().to8Bit(1));
191 std::string ext = s.GetFile();
192 ext = ext.substr(ext.rfind(".")+1);
193 ToLower(ext);
195 if (!isInitialized)
196 Init();
198 w->Clear();
199 w->Reset();
201 w->ResizeList(24);
203 for (size_t i = 0; i < 7; ++i)
204 w->Static(i, 1);
206 w->IntoSeparator(7);
207 w->IntoSeparator(19);
208 w->IntoSeparator(21);
210 if (!extendedTagsSupported(f.file()))
212 w->Static(10, 1);
213 for (size_t i = 15; i <= 17; ++i)
214 w->Static(i, 1);
217 w->Highlight(8);
219 w->at(0) << fmtBold << Config.color1 << "Song name: " << fmtBoldEnd << Config.color2 << s.GetName() << clEnd;
220 w->at(1) << fmtBold << Config.color1 << "Location in DB: " << fmtBoldEnd << Config.color2;
221 ShowTag(w->at(1), s.GetDirectory());
222 w->at(1) << clEnd;
223 w->at(3) << fmtBold << Config.color1 << "Length: " << fmtBoldEnd << Config.color2 << s.GetLength() << clEnd;
224 w->at(4) << fmtBold << Config.color1 << "Bitrate: " << fmtBoldEnd << Config.color2 << f.audioProperties()->bitrate() << " kbps" << clEnd;
225 w->at(5) << fmtBold << Config.color1 << "Sample rate: " << fmtBoldEnd << Config.color2 << f.audioProperties()->sampleRate() << " Hz" << clEnd;
226 w->at(6) << fmtBold << Config.color1 << "Channels: " << fmtBoldEnd << Config.color2 << (f.audioProperties()->channels() == 1 ? "Mono" : "Stereo") << clDefault;
228 unsigned pos = 8;
229 for (const Info::Metadata *m = Info::Tags; m->Name; ++m, ++pos)
231 w->at(pos) << fmtBold << m->Name << ":" << fmtBoldEnd << ' ';
232 ShowTag(w->at(pos), s.GetTags(m->Get));
235 w->at(20) << fmtBold << "Filename:" << fmtBoldEnd << ' ' << s.GetName();
237 w->at(22) << "Save";
238 w->at(23) << "Cancel";
239 return true;
242 bool TinyTagEditor::extendedTagsSupported(TagLib::File *f)
244 return dynamic_cast<TagLib::MPEG::File *>(f)
245 || dynamic_cast<TagLib::Ogg::Vorbis::File *>(f)
246 || dynamic_cast<TagLib::FLAC::File *>(f);
249 #endif // HAVE_TAGLIB_H