1 /***************************************************************************
2 * Copyright (C) 2008-2014 by Andrzej Rybczak *
3 * electricityispower@gmail.com *
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. *
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. *
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"
25 #include <boost/locale/conversion.hpp>
36 #include "menu_impl.h"
37 #include "song_info.h"
39 #include "search_engine.h"
40 #include "statusbar.h"
41 #include "tag_editor.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();
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
);
72 void TinyTagEditor::switchTo()
74 using Global::myScreen
;
75 if (itsEdited
.isStream())
77 Statusbar::print("Streams can't be edited");
81 m_previous_screen
= myScreen
;
82 SwitchTo::execute(this);
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())
106 if (me
.bstate
& (BUTTON1_PRESSED
| BUTTON3_PRESSED
))
110 if (me
.bstate
& BUTTON3_PRESSED
)
117 Screen
<WindowType
>::mouseButtonPressed(me
);
120 /**********************************************************************/
122 bool TinyTagEditor::actionRunnable()
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());
160 Statusbar::print("Updating tags...");
161 if (Tags::write(itsEdited
))
163 Statusbar::print("Tags updated");
164 if (itsEdited
.isFromDatabase())
165 Mpd
.UpdateDirectory(itsEdited
.getDirectory());
168 if (m_previous_screen
== myPlaylist
)
169 myPlaylist
->main().current()->value() = itsEdited
;
170 else if (m_previous_screen
== myBrowser
)
171 myBrowser
->requestUpdate();
175 Statusbar::print("Error while writing tags");
178 m_previous_screen
->switchTo();
181 /**********************************************************************/
183 void TinyTagEditor::SetEdited(const MPD::Song
&s
)
185 if (auto ms
= dynamic_cast<const MPD::MutableSong
*>(&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());
202 std::string ext
= itsEdited
.getURI();
203 ext
= boost::locale::to_lower(ext
.substr(ext
.rfind(".")+1));
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);
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
;
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";
249 #endif // HAVE_TAGLIB_H