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::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());
135 Statusbar::print("Updating tags...");
136 if (Tags::write(itsEdited
))
138 Statusbar::print("Tags updated");
139 if (itsEdited
.isFromDatabase())
140 Mpd
.UpdateDirectory(itsEdited
.getDirectory());
143 if (m_previous_screen
== myPlaylist
)
144 myPlaylist
->main().current()->value() = itsEdited
;
145 else if (m_previous_screen
== myBrowser
)
146 myBrowser
->requestUpdate();
150 Statusbar::print("Error while writing tags");
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())
160 if (me
.bstate
& (BUTTON1_PRESSED
| BUTTON3_PRESSED
))
164 if (me
.bstate
& BUTTON3_PRESSED
)
171 Screen
<WindowType
>::mouseButtonPressed(me
);
174 void TinyTagEditor::SetEdited(const MPD::Song
&s
)
176 if (auto ms
= dynamic_cast<const MPD::MutableSong
*>(&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());
193 std::string ext
= itsEdited
.getURI();
194 ext
= boost::locale::to_lower(ext
.substr(ext
.rfind(".")+1));
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);
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
;
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";
240 #endif // HAVE_TAGLIB_H