format: shorten date by simple truncation
[ncmpcpp.git] / src / tiny_tag_editor.cpp
bloba18698b3fbdfcd117d8cdb875234d643e779eee4
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::enterPressed()
104 size_t option = w.choice();
105 if (option < 19) // separator after comment
107 Statusbar::ScopedLock slock;
108 size_t pos = option-8;
109 Statusbar::put() << NC::Format::Bold << SongInfo::Tags[pos].Name << ": " << NC::Format::NoBold;
110 itsEdited.setTags(SongInfo::Tags[pos].Set, Global::wFooter->prompt(
111 itsEdited.getTags(SongInfo::Tags[pos].Get)));
112 w.at(option).value().clear();
113 w.at(option).value() << NC::Format::Bold << SongInfo::Tags[pos].Name << ':' << NC::Format::NoBold << ' ';
114 ShowTag(w.at(option).value(), itsEdited.getTags(SongInfo::Tags[pos].Get));
116 else if (option == 20)
118 Statusbar::ScopedLock slock;
119 Statusbar::put() << NC::Format::Bold << "Filename: " << NC::Format::NoBold;
120 std::string filename = itsEdited.getNewName().empty() ? itsEdited.getName() : itsEdited.getNewName();
121 size_t dot = filename.rfind(".");
122 std::string extension = filename.substr(dot);
123 filename = filename.substr(0, dot);
124 std::string new_name = Global::wFooter->prompt(filename);
125 if (!new_name.empty())
127 itsEdited.setNewName(new_name + extension);
128 w.at(option).value().clear();
129 w.at(option).value() << NC::Format::Bold << "Filename:" << NC::Format::NoBold << ' ' << (itsEdited.getNewName().empty() ? itsEdited.getName() : itsEdited.getNewName());
133 if (option == 22)
135 Statusbar::print("Updating tags...");
136 if (Tags::write(itsEdited))
138 Statusbar::print("Tags updated");
139 if (itsEdited.isFromDatabase())
140 Mpd.UpdateDirectory(itsEdited.getDirectory());
141 else
143 if (m_previous_screen == myPlaylist)
144 myPlaylist->main().current()->value() = itsEdited;
145 else if (m_previous_screen == myBrowser)
146 myBrowser->requestUpdate();
149 else
150 Statusbar::print("Error while writing tags");
152 if (option > 21)
153 m_previous_screen->switchTo();
156 void TinyTagEditor::mouseButtonPressed(MEVENT me)
158 if (w.empty() || !w.hasCoords(me.x, me.y) || size_t(me.y) >= w.size())
159 return;
160 if (me.bstate & (BUTTON1_PRESSED | BUTTON3_PRESSED))
162 if (!w.Goto(me.y))
163 return;
164 if (me.bstate & BUTTON3_PRESSED)
166 w.refresh();
167 enterPressed();
170 else
171 Screen<WindowType>::mouseButtonPressed(me);
174 void TinyTagEditor::SetEdited(const MPD::Song &s)
176 if (auto ms = dynamic_cast<const MPD::MutableSong *>(&s))
177 itsEdited = *ms;
178 else
179 itsEdited = s;
182 bool TinyTagEditor::getTags()
184 std::string path_to_file;
185 if (itsEdited.isFromDatabase())
186 path_to_file += Config.mpd_music_dir;
187 path_to_file += itsEdited.getURI();
189 TagLib::FileRef f(path_to_file.c_str());
190 if (f.isNull())
191 return false;
193 std::string ext = itsEdited.getURI();
194 ext = boost::locale::to_lower(ext.substr(ext.rfind(".")+1));
196 w.clear();
197 w.reset();
199 w.resizeList(24);
201 for (size_t i = 0; i < 7; ++i)
202 w.at(i).setInactive(true);
204 w.at(7).setSeparator(true);
205 w.at(19).setSeparator(true);
206 w.at(21).setSeparator(true);
208 if (!Tags::extendedSetSupported(f.file()))
210 w.at(10).setInactive(true);
211 for (size_t i = 15; i <= 17; ++i)
212 w.at(i).setInactive(true);
215 w.highlight(8);
217 w.at(0).value() << NC::Format::Bold << Config.color1 << "Song name: " << NC::Format::NoBold << Config.color2 << itsEdited.getName() << NC::Color::End;
218 w.at(1).value() << NC::Format::Bold << Config.color1 << "Location in DB: " << NC::Format::NoBold << Config.color2;
219 ShowTag(w.at(1).value(), itsEdited.getDirectory());
220 w.at(1).value() << NC::Color::End;
221 w.at(3).value() << NC::Format::Bold << Config.color1 << "Length: " << NC::Format::NoBold << Config.color2 << itsEdited.getLength() << NC::Color::End;
222 w.at(4).value() << NC::Format::Bold << Config.color1 << "Bitrate: " << NC::Format::NoBold << Config.color2 << f.audioProperties()->bitrate() << " kbps" << NC::Color::End;
223 w.at(5).value() << NC::Format::Bold << Config.color1 << "Sample rate: " << NC::Format::NoBold << Config.color2 << f.audioProperties()->sampleRate() << " Hz" << NC::Color::End;
224 w.at(6).value() << NC::Format::Bold << Config.color1 << "Channels: " << NC::Format::NoBold << Config.color2 << (f.audioProperties()->channels() == 1 ? "Mono" : "Stereo") << NC::Color::Default;
226 unsigned pos = 8;
227 for (const SongInfo::Metadata *m = SongInfo::Tags; m->Name; ++m, ++pos)
229 w.at(pos).value() << NC::Format::Bold << m->Name << ":" << NC::Format::NoBold << ' ';
230 ShowTag(w.at(pos).value(), itsEdited.getTags(m->Get));
233 w.at(20).value() << NC::Format::Bold << "Filename:" << NC::Format::NoBold << ' ' << itsEdited.getName();
235 w.at(22).value() << "Save";
236 w.at(23).value() << "Cancel";
237 return true;
240 #endif // HAVE_TAGLIB_H