change version to 0.7.3
[ncmpcpp.git] / src / tiny_tag_editor.cpp
bloba029f470c00b410eee87a70ef7a06c9b34a04276
1 /***************************************************************************
2 * Copyright (C) 2008-2014 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 #include <boost/locale/conversion.hpp>
27 // taglib includes
28 #include <fileref.h>
29 #include <tag.h>
31 #include "browser.h"
32 #include "charset.h"
33 #include "display.h"
34 #include "helpers.h"
35 #include "global.h"
36 #include "menu_impl.h"
37 #include "song_info.h"
38 #include "playlist.h"
39 #include "search_engine.h"
40 #include "statusbar.h"
41 #include "tag_editor.h"
42 #include "title.h"
43 #include "tags.h"
44 #include "screen_switcher.h"
45 #include "utility/string.h"
47 using Global::MainHeight;
48 using Global::MainStartY;
50 TinyTagEditor *myTinyTagEditor;
52 TinyTagEditor::TinyTagEditor()
53 : Screen(NC::Menu<NC::Buffer>(0, MainStartY, COLS, MainHeight, "", Config.main_color, NC::Border()))
55 w.setHighlightColor(Config.main_highlight_color);
56 w.cyclicScrolling(Config.use_cyclic_scrolling);
57 w.centeredCursor(Config.centered_cursor);
58 w.setItemDisplayer([](NC::Menu<NC::Buffer> &menu) {
59 menu << menu.drawn()->value();
60 });
63 void TinyTagEditor::resize()
65 size_t x_offset, width;
66 getWindowResizeParams(x_offset, width);
67 w.resize(width, MainHeight);
68 w.moveTo(x_offset, MainStartY);
69 hasToBeResized = 0;
72 void TinyTagEditor::switchTo()
74 using Global::myScreen;
75 if (itsEdited.isStream())
77 Statusbar::print("Streams can't be edited");
79 else if (getTags())
81 m_previous_screen = myScreen;
82 SwitchTo::execute(this);
83 drawHeader();
85 else
87 std::string full_path;
88 if (itsEdited.isFromDatabase())
89 full_path += Config.mpd_music_dir;
90 full_path += itsEdited.getURI();
92 const char msg[] = "Couldn't read file \"%1%\"";
93 Statusbar::printf(msg, wideShorten(full_path, COLS-const_strlen(msg)));
97 std::wstring TinyTagEditor::title()
99 return L"Tiny tag editor";
102 void TinyTagEditor::mouseButtonPressed(MEVENT me)
104 if (w.empty() || !w.hasCoords(me.x, me.y) || size_t(me.y) >= w.size())
105 return;
106 if (me.bstate & (BUTTON1_PRESSED | BUTTON3_PRESSED))
108 if (!w.Goto(me.y))
109 return;
110 if (me.bstate & BUTTON3_PRESSED)
112 w.refresh();
113 runAction();
116 else
117 Screen<WindowType>::mouseButtonPressed(me);
120 /**********************************************************************/
122 bool TinyTagEditor::actionRunnable()
124 return !w.empty();
127 void TinyTagEditor::runAction()
129 size_t option = w.choice();
130 if (option < 19) // separator after comment
132 Statusbar::ScopedLock slock;
133 size_t pos = option-8;
134 Statusbar::put() << NC::Format::Bold << SongInfo::Tags[pos].Name << ": " << NC::Format::NoBold;
135 itsEdited.setTags(SongInfo::Tags[pos].Set, Global::wFooter->prompt(
136 itsEdited.getTags(SongInfo::Tags[pos].Get)));
137 w.at(option).value().clear();
138 w.at(option).value() << NC::Format::Bold << SongInfo::Tags[pos].Name << ':' << NC::Format::NoBold << ' ';
139 ShowTag(w.at(option).value(), itsEdited.getTags(SongInfo::Tags[pos].Get));
141 else if (option == 20)
143 Statusbar::ScopedLock slock;
144 Statusbar::put() << NC::Format::Bold << "Filename: " << NC::Format::NoBold;
145 std::string filename = itsEdited.getNewName().empty() ? itsEdited.getName() : itsEdited.getNewName();
146 size_t dot = filename.rfind(".");
147 std::string extension = filename.substr(dot);
148 filename = filename.substr(0, dot);
149 std::string new_name = Global::wFooter->prompt(filename);
150 if (!new_name.empty())
152 itsEdited.setNewName(new_name + extension);
153 w.at(option).value().clear();
154 w.at(option).value() << NC::Format::Bold << "Filename:" << NC::Format::NoBold << ' ' << (itsEdited.getNewName().empty() ? itsEdited.getName() : itsEdited.getNewName());
158 if (option == 22)
160 Statusbar::print("Updating tags...");
161 if (Tags::write(itsEdited))
163 Statusbar::print("Tags updated");
164 if (itsEdited.isFromDatabase())
165 Mpd.UpdateDirectory(itsEdited.getDirectory());
166 else
168 if (m_previous_screen == myPlaylist)
169 myPlaylist->main().current()->value() = itsEdited;
170 else if (m_previous_screen == myBrowser)
171 myBrowser->requestUpdate();
174 else
175 Statusbar::print("Error while writing tags");
177 if (option > 21)
178 m_previous_screen->switchTo();
181 /**********************************************************************/
183 void TinyTagEditor::SetEdited(const MPD::Song &s)
185 if (auto ms = dynamic_cast<const MPD::MutableSong *>(&s))
186 itsEdited = *ms;
187 else
188 itsEdited = s;
191 bool TinyTagEditor::getTags()
193 std::string path_to_file;
194 if (itsEdited.isFromDatabase())
195 path_to_file += Config.mpd_music_dir;
196 path_to_file += itsEdited.getURI();
198 TagLib::FileRef f(path_to_file.c_str());
199 if (f.isNull())
200 return false;
202 std::string ext = itsEdited.getURI();
203 ext = boost::locale::to_lower(ext.substr(ext.rfind(".")+1));
205 w.clear();
206 w.reset();
208 w.resizeList(24);
210 for (size_t i = 0; i < 7; ++i)
211 w.at(i).setInactive(true);
213 w.at(7).setSeparator(true);
214 w.at(19).setSeparator(true);
215 w.at(21).setSeparator(true);
217 if (!Tags::extendedSetSupported(f.file()))
219 w.at(10).setInactive(true);
220 for (size_t i = 15; i <= 17; ++i)
221 w.at(i).setInactive(true);
224 w.highlight(8);
226 w.at(0).value() << NC::Format::Bold << Config.color1 << "Song name: " << NC::Format::NoBold << Config.color2 << itsEdited.getName() << NC::Color::End;
227 w.at(1).value() << NC::Format::Bold << Config.color1 << "Location in DB: " << NC::Format::NoBold << Config.color2;
228 ShowTag(w.at(1).value(), itsEdited.getDirectory());
229 w.at(1).value() << NC::Color::End;
230 w.at(3).value() << NC::Format::Bold << Config.color1 << "Length: " << NC::Format::NoBold << Config.color2 << itsEdited.getLength() << NC::Color::End;
231 w.at(4).value() << NC::Format::Bold << Config.color1 << "Bitrate: " << NC::Format::NoBold << Config.color2 << f.audioProperties()->bitrate() << " kbps" << NC::Color::End;
232 w.at(5).value() << NC::Format::Bold << Config.color1 << "Sample rate: " << NC::Format::NoBold << Config.color2 << f.audioProperties()->sampleRate() << " Hz" << NC::Color::End;
233 w.at(6).value() << NC::Format::Bold << Config.color1 << "Channels: " << NC::Format::NoBold << Config.color2 << (f.audioProperties()->channels() == 1 ? "Mono" : "Stereo") << NC::Color::Default;
235 unsigned pos = 8;
236 for (const SongInfo::Metadata *m = SongInfo::Tags; m->Name; ++m, ++pos)
238 w.at(pos).value() << NC::Format::Bold << m->Name << ":" << NC::Format::NoBold << ' ';
239 ShowTag(w.at(pos).value(), itsEdited.getTags(m->Get));
242 w.at(20).value() << NC::Format::Bold << "Filename:" << NC::Format::NoBold << ' ' << itsEdited.getName();
244 w.at(22).value() << "Save";
245 w.at(23).value() << "Cancel";
246 return true;
249 #endif // HAVE_TAGLIB_H