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 "song_info.h"
38 #include "search_engine.h"
39 #include "statusbar.h"
40 #include "tag_editor.h"
43 #include "screen_switcher.h"
44 #include "utility/string.h"
46 using Global::MainHeight
;
47 using Global::MainStartY
;
49 TinyTagEditor
*myTinyTagEditor
;
51 TinyTagEditor::TinyTagEditor()
52 : Screen(NC::Menu
<NC::Buffer
>(0, MainStartY
, COLS
, MainHeight
, "", Config
.main_color
, NC::Border::None
))
54 w
.setHighlightColor(Config
.main_highlight_color
);
55 w
.cyclicScrolling(Config
.use_cyclic_scrolling
);
56 w
.centeredCursor(Config
.centered_cursor
);
57 w
.setItemDisplayer([](NC::Menu
<NC::Buffer
> &menu
) {
58 menu
<< menu
.drawn()->value();
62 void TinyTagEditor::resize()
64 size_t x_offset
, width
;
65 getWindowResizeParams(x_offset
, width
);
66 w
.resize(width
, MainHeight
);
67 w
.moveTo(x_offset
, MainStartY
);
71 void TinyTagEditor::switchTo()
73 using Global::myScreen
;
74 if (itsEdited
.isStream())
76 Statusbar::print("Streams can't be edited");
80 m_previous_screen
= myScreen
;
81 SwitchTo::execute(this);
86 std::string full_path
;
87 if (itsEdited
.isFromDatabase())
88 full_path
+= Config
.mpd_music_dir
;
89 full_path
+= itsEdited
.getURI();
91 const char msg
[] = "Couldn't read file \"%1%\"";
92 Statusbar::printf(msg
, wideShorten(full_path
, COLS
-const_strlen(msg
)));
96 std::wstring
TinyTagEditor::title()
98 return L
"Tiny tag editor";
101 void TinyTagEditor::enterPressed()
103 size_t option
= w
.choice();
105 if (option
< 19) // separator after comment
107 size_t pos
= option
-8;
108 Statusbar::put() << NC::Format::Bold
<< SongInfo::Tags
[pos
].Name
<< ": " << NC::Format::NoBold
;
109 itsEdited
.setTags(SongInfo::Tags
[pos
].Set
, Global::wFooter
->getString(
110 itsEdited
.getTags(SongInfo::Tags
[pos
].Get
, Config
.tags_separator
)), Config
.tags_separator
);
111 w
.at(option
).value().clear();
112 w
.at(option
).value() << NC::Format::Bold
<< SongInfo::Tags
[pos
].Name
<< ':' << NC::Format::NoBold
<< ' ';
113 ShowTag(w
.at(option
).value(), itsEdited
.getTags(SongInfo::Tags
[pos
].Get
, Config
.tags_separator
));
115 else if (option
== 20)
117 Statusbar::put() << NC::Format::Bold
<< "Filename: " << NC::Format::NoBold
;
118 std::string filename
= itsEdited
.getNewName().empty() ? itsEdited
.getName() : itsEdited
.getNewName();
119 size_t dot
= filename
.rfind(".");
120 std::string extension
= filename
.substr(dot
);
121 filename
= filename
.substr(0, dot
);
122 std::string new_name
= Global::wFooter
->getString(filename
);
123 if (!new_name
.empty())
125 itsEdited
.setNewName(new_name
+ extension
);
126 w
.at(option
).value().clear();
127 w
.at(option
).value() << NC::Format::Bold
<< "Filename:" << NC::Format::NoBold
<< ' ' << (itsEdited
.getNewName().empty() ? itsEdited
.getName() : itsEdited
.getNewName());
134 Statusbar::print("Updating tags...");
135 if (Tags::write(itsEdited
))
137 Statusbar::print("Tags updated");
138 if (itsEdited
.isFromDatabase())
139 Mpd
.UpdateDirectory(itsEdited
.getDirectory());
142 if (m_previous_screen
== myPlaylist
)
143 myPlaylist
->main().current().value() = itsEdited
;
144 else if (m_previous_screen
== myBrowser
)
145 myBrowser
->GetDirectory(myBrowser
->CurrentDir());
149 Statusbar::print("Error while writing tags");
152 m_previous_screen
->switchTo();
155 void TinyTagEditor::mouseButtonPressed(MEVENT me
)
157 if (w
.empty() || !w
.hasCoords(me
.x
, me
.y
) || size_t(me
.y
) >= w
.size())
159 if (me
.bstate
& (BUTTON1_PRESSED
| BUTTON3_PRESSED
))
163 if (me
.bstate
& BUTTON3_PRESSED
)
170 Screen
<WindowType
>::mouseButtonPressed(me
);
173 void TinyTagEditor::SetEdited(const MPD::Song
&s
)
175 if (auto ms
= dynamic_cast<const MPD::MutableSong
*>(&s
))
181 bool TinyTagEditor::getTags()
183 std::string path_to_file
;
184 if (itsEdited
.isFromDatabase())
185 path_to_file
+= Config
.mpd_music_dir
;
186 path_to_file
+= itsEdited
.getURI();
188 TagLib::FileRef
f(path_to_file
.c_str());
192 std::string ext
= itsEdited
.getURI();
193 ext
= boost::locale::to_lower(ext
.substr(ext
.rfind(".")+1));
200 for (size_t i
= 0; i
< 7; ++i
)
201 w
.at(i
).setInactive(true);
203 w
.at(7).setSeparator(true);
204 w
.at(19).setSeparator(true);
205 w
.at(21).setSeparator(true);
207 if (!Tags::extendedSetSupported(f
.file()))
209 w
.at(10).setInactive(true);
210 for (size_t i
= 15; i
<= 17; ++i
)
211 w
.at(i
).setInactive(true);
216 w
.at(0).value() << NC::Format::Bold
<< Config
.color1
<< "Song name: " << NC::Format::NoBold
<< Config
.color2
<< itsEdited
.getName() << NC::Color::End
;
217 w
.at(1).value() << NC::Format::Bold
<< Config
.color1
<< "Location in DB: " << NC::Format::NoBold
<< Config
.color2
;
218 ShowTag(w
.at(1).value(), itsEdited
.getDirectory());
219 w
.at(1).value() << NC::Color::End
;
220 w
.at(3).value() << NC::Format::Bold
<< Config
.color1
<< "Length: " << NC::Format::NoBold
<< Config
.color2
<< itsEdited
.getLength() << NC::Color::End
;
221 w
.at(4).value() << NC::Format::Bold
<< Config
.color1
<< "Bitrate: " << NC::Format::NoBold
<< Config
.color2
<< f
.audioProperties()->bitrate() << " kbps" << NC::Color::End
;
222 w
.at(5).value() << NC::Format::Bold
<< Config
.color1
<< "Sample rate: " << NC::Format::NoBold
<< Config
.color2
<< f
.audioProperties()->sampleRate() << " Hz" << NC::Color::End
;
223 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 for (const SongInfo::Metadata
*m
= SongInfo::Tags
; m
->Name
; ++m
, ++pos
)
228 w
.at(pos
).value() << NC::Format::Bold
<< m
->Name
<< ":" << NC::Format::NoBold
<< ' ';
229 ShowTag(w
.at(pos
).value(), itsEdited
.getTags(m
->Get
, Config
.tags_separator
));
232 w
.at(20).value() << NC::Format::Bold
<< "Filename:" << NC::Format::NoBold
<< ' ' << itsEdited
.getName();
234 w
.at(22).value() << "Save";
235 w
.at(23).value() << "Cancel";
239 #endif // HAVE_TAGLIB_H