Support attaching format information to selected color variables
This commit is contained in:
19
doc/config
19
doc/config
@@ -328,8 +328,6 @@
|
||||
##
|
||||
#progressbar_look = =>
|
||||
#
|
||||
#progressbar_boldness = yes
|
||||
#
|
||||
## Available values: database, playlist.
|
||||
##
|
||||
#default_place_to_search_in = database
|
||||
@@ -496,6 +494,15 @@
|
||||
## the bottom of the help screen for list of available colors
|
||||
## and their numerical values.
|
||||
##
|
||||
## Moreover, it is possible to attach format information to
|
||||
## selected color variables by appending to their end a
|
||||
## colon followed by one or more format flags, e.g. black:b
|
||||
## or red:ur. The following variables support this syntax:
|
||||
## visualizer_color, color1, color2, empty_tag_color,
|
||||
## volume_color, state_line_color, state_flags_color,
|
||||
## progressbar_color, progressbar_elapsed_color,
|
||||
## alternative_ui_separator_color.
|
||||
##
|
||||
## Note: due to technical limitations of ncurses, if 256 colors
|
||||
## are used, it is possible to either use only the colors with
|
||||
## default background color, or all pairs from 1_1 up to 254_127,
|
||||
@@ -512,7 +519,7 @@
|
||||
#
|
||||
#state_line_color = default
|
||||
#
|
||||
#state_flags_color = default
|
||||
#state_flags_color = default:b
|
||||
#
|
||||
#main_window_color = yellow
|
||||
#
|
||||
@@ -522,13 +529,13 @@
|
||||
#
|
||||
#main_window_highlight_color = yellow
|
||||
#
|
||||
#progressbar_color = black
|
||||
#progressbar_color = black:b
|
||||
#
|
||||
#progressbar_elapsed_color = green
|
||||
#progressbar_elapsed_color = green:b
|
||||
#
|
||||
#statusbar_color = default
|
||||
#
|
||||
#alternative_ui_separator_color = black
|
||||
#alternative_ui_separator_color = black:b
|
||||
#
|
||||
#active_column_color = red
|
||||
#
|
||||
|
||||
@@ -204,9 +204,6 @@ If enabled, currently highlighted position in the list will be always centered.
|
||||
.B progressbar_look = TEXT
|
||||
This variable defines the look of progressbar. Note that it has to be exactly two or three characters long.
|
||||
.TP
|
||||
.B progressbar_boldness = yes/no
|
||||
This variable defines whether progressbar should be displayed in bold or not.
|
||||
.TP
|
||||
.B default_place_to_search_in = database/playlist
|
||||
If set to "playlist", Search engine will perform searching in current MPD playlist rather than in music database.
|
||||
.TP
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
bin_PROGRAMS = ncmpcpp
|
||||
ncmpcpp_SOURCES = \
|
||||
curses/formatted_color.cpp \
|
||||
curses/scrollpad.cpp \
|
||||
curses/window.cpp \
|
||||
screens/browser.cpp \
|
||||
@@ -57,6 +58,7 @@ INCLUDES= $(all_includes)
|
||||
# the library search path.
|
||||
ncmpcpp_LDFLAGS = $(all_libraries)
|
||||
noinst_HEADERS = \
|
||||
curses/formatted_color.h \
|
||||
curses/menu.h \
|
||||
curses/menu_impl.h \
|
||||
curses/scrollpad.h \
|
||||
|
||||
83
src/curses/formatted_color.cpp
Normal file
83
src/curses/formatted_color.cpp
Normal file
@@ -0,0 +1,83 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008-2016 by Andrzej Rybczak *
|
||||
* electricityispower@gmail.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include "formatted_color.h"
|
||||
|
||||
namespace {
|
||||
|
||||
void verifyFormats(const NC::FormattedColor::Formats &formats)
|
||||
{
|
||||
for (auto &fmt : formats)
|
||||
{
|
||||
if (fmt == NC::Format::NoBold
|
||||
|| fmt == NC::Format::NoUnderline
|
||||
|| fmt == NC::Format::NoReverse
|
||||
|| fmt == NC::Format::NoAltCharset)
|
||||
throw std::logic_error("FormattedColor can't hold disabling formats");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
NC::FormattedColor::FormattedColor(Color color_, Formats formats_)
|
||||
{
|
||||
if (color_ == NC::Color::End)
|
||||
throw std::logic_error("FormattedColor can't hold Color::End");
|
||||
m_color = std::move(color_);
|
||||
verifyFormats(formats_);
|
||||
m_formats = std::move(formats_);
|
||||
}
|
||||
|
||||
std::istream &NC::operator>>(std::istream &is, NC::FormattedColor &fc)
|
||||
{
|
||||
NC::Color c;
|
||||
is >> c;
|
||||
if (!is.eof() && is.peek() == ':')
|
||||
{
|
||||
is.get();
|
||||
NC::FormattedColor::Formats formats;
|
||||
while (!is.eof() && isalpha(is.peek()))
|
||||
{
|
||||
char flag = is.get();
|
||||
switch (flag)
|
||||
{
|
||||
case 'b':
|
||||
formats.push_back(NC::Format::Bold);
|
||||
break;
|
||||
case 'u':
|
||||
formats.push_back(NC::Format::Underline);
|
||||
break;
|
||||
case 'r':
|
||||
formats.push_back(NC::Format::Reverse);
|
||||
break;
|
||||
case 'a':
|
||||
formats.push_back(NC::Format::AltCharset);
|
||||
break;
|
||||
default:
|
||||
is.setstate(std::ios::failbit);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fc = NC::FormattedColor(c, std::move(formats));
|
||||
}
|
||||
else
|
||||
fc = NC::FormattedColor(c, {});
|
||||
return is;
|
||||
}
|
||||
81
src/curses/formatted_color.h
Normal file
81
src/curses/formatted_color.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/***************************************************************************
|
||||
* Copyright (C) 2008-2016 by Andrzej Rybczak *
|
||||
* electricityispower@gmail.com *
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* This program is distributed in the hope that it will be useful, *
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
||||
* GNU General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program; if not, write to the *
|
||||
* Free Software Foundation, Inc., *
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef NCMPCPP_FORMATTED_COLOR_H
|
||||
#define NCMPCPP_FORMATTED_COLOR_H
|
||||
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/range/adaptor/reversed.hpp>
|
||||
#include "window.h"
|
||||
|
||||
namespace NC {
|
||||
|
||||
struct FormattedColor
|
||||
{
|
||||
struct End
|
||||
{
|
||||
End(const FormattedColor &fc)
|
||||
: m_fc(fc)
|
||||
{ }
|
||||
|
||||
const FormattedColor &base() const { return m_fc; }
|
||||
|
||||
private:
|
||||
const FormattedColor &m_fc;
|
||||
};
|
||||
|
||||
typedef std::vector<Format> Formats;
|
||||
|
||||
FormattedColor() { }
|
||||
|
||||
FormattedColor(Color color_, Formats formats_);
|
||||
|
||||
const Color &color() const { return m_color; }
|
||||
const Formats &formats() const { return m_formats; }
|
||||
|
||||
private:
|
||||
Color m_color;
|
||||
Formats m_formats;
|
||||
};
|
||||
|
||||
std::istream &operator>>(std::istream &is, FormattedColor &fc);
|
||||
|
||||
template <typename OutputStreamT>
|
||||
OutputStreamT &operator<<(OutputStreamT &os, const FormattedColor &fc)
|
||||
{
|
||||
os << fc.color();
|
||||
for (auto &fmt : fc.formats())
|
||||
os << fmt;
|
||||
return os;
|
||||
}
|
||||
|
||||
template <typename OutputStreamT>
|
||||
OutputStreamT &operator<<(OutputStreamT &os, const FormattedColor::End &rfc)
|
||||
{
|
||||
if (rfc.base().color() != Color::Default)
|
||||
os << Color::End;
|
||||
for (auto &fmt : boost::adaptors::reverse(rfc.base().formats()))
|
||||
os << reverseFormat(fmt);
|
||||
return os;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // NCMPCPP_FORMATTED_COLOR_H
|
||||
@@ -259,36 +259,67 @@ std::istream &operator>>(std::istream &is, Color &c)
|
||||
}
|
||||
return result;
|
||||
};
|
||||
std::string sc;
|
||||
is >> sc;
|
||||
|
||||
auto get_color = [](std::istream &is_) {
|
||||
std::string result;
|
||||
while (!is_.eof() && isalnum(is_.peek()))
|
||||
result.push_back(is_.get());
|
||||
return result;
|
||||
};
|
||||
|
||||
std::string sc = get_color(is);
|
||||
|
||||
if (sc == "default")
|
||||
c = Color::Default;
|
||||
c = Color::Default;
|
||||
else if (sc == "end")
|
||||
c = Color::End;
|
||||
else
|
||||
{
|
||||
short value = get_single_color(sc, false);
|
||||
if (value != -1)
|
||||
c = Color(value, NC::Color::transparent);
|
||||
else
|
||||
short fg = get_single_color(sc, false);
|
||||
if (fg == -1)
|
||||
is.setstate(std::ios::failbit);
|
||||
// Check if there is background color
|
||||
else if (!is.eof() && is.peek() == '_')
|
||||
{
|
||||
size_t underscore = sc.find('_');
|
||||
if (underscore != std::string::npos)
|
||||
{
|
||||
short fg = get_single_color(sc.substr(0, underscore), false);
|
||||
short bg = get_single_color(sc.substr(underscore+1), true);
|
||||
if (fg != -1 && bg != -1)
|
||||
c = Color(fg, bg);
|
||||
else
|
||||
is.setstate(std::ios::failbit);
|
||||
}
|
||||
else
|
||||
is.get();
|
||||
sc = get_color(is);
|
||||
short bg = get_single_color(sc, true);
|
||||
if (bg == -1)
|
||||
is.setstate(std::ios::failbit);
|
||||
else
|
||||
c = Color(fg, bg);
|
||||
}
|
||||
else
|
||||
c = Color(fg, NC::Color::transparent);
|
||||
}
|
||||
return is;
|
||||
}
|
||||
|
||||
NC::Format reverseFormat(NC::Format fmt)
|
||||
{
|
||||
switch (fmt)
|
||||
{
|
||||
case NC::Format::Bold:
|
||||
return NC::Format::NoBold;
|
||||
case NC::Format::NoBold:
|
||||
return NC::Format::Bold;
|
||||
case NC::Format::Underline:
|
||||
return NC::Format::NoUnderline;
|
||||
case NC::Format::NoUnderline:
|
||||
return NC::Format::Underline;
|
||||
case NC::Format::Reverse:
|
||||
return NC::Format::NoReverse;
|
||||
case NC::Format::NoReverse:
|
||||
return NC::Format::Reverse;
|
||||
case NC::Format::AltCharset:
|
||||
return NC::Format::NoAltCharset;
|
||||
case NC::Format::NoAltCharset:
|
||||
return NC::Format::AltCharset;
|
||||
}
|
||||
// Unreachable, silence GCC.
|
||||
return fmt;
|
||||
}
|
||||
|
||||
namespace Mouse {
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -149,7 +149,7 @@ struct Color
|
||||
static const short transparent;
|
||||
static const short previous;
|
||||
|
||||
Color() : m_impl(0, transparent, true, false) { }
|
||||
Color() : m_impl(0, 0, true, false) { }
|
||||
Color(short foreground_value, short background_value,
|
||||
bool is_default = false, bool is_end = false)
|
||||
: m_impl(foreground_value, background_value, is_default, is_end)
|
||||
@@ -201,6 +201,8 @@ enum class Format {
|
||||
AltCharset, NoAltCharset
|
||||
};
|
||||
|
||||
NC::Format reverseFormat(NC::Format fmt);
|
||||
|
||||
/// This indicates how much the window has to be scrolled
|
||||
enum class Scroll { Up, Down, PageUp, PageDown, Home, End };
|
||||
|
||||
|
||||
@@ -349,7 +349,9 @@ void Display::Tags(NC::Menu<MPD::MutableSong> &menu)
|
||||
menu << Charset::utf8ToLocale(s.getName());
|
||||
else
|
||||
menu << Charset::utf8ToLocale(s.getName())
|
||||
<< Config.color2 << " -> " << NC::Color::End
|
||||
<< Config.color2
|
||||
<< " -> "
|
||||
<< NC::FormattedColor::End(Config.color2)
|
||||
<< Charset::utf8ToLocale(s.getNewName());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -487,14 +487,24 @@ template <typename T> void ShowTime(T &buf, size_t length, bool short_names)
|
||||
buf << length << (short_names ? "s" : (length == 1 ? " second" : " seconds"));
|
||||
}
|
||||
|
||||
template <typename BufferT> void ShowTag(BufferT &buf, const std::string &tag)
|
||||
template <typename BufferT>
|
||||
void ShowTag(BufferT &buf, const std::string &tag)
|
||||
{
|
||||
if (tag.empty())
|
||||
buf << Config.empty_tags_color << Config.empty_tag << NC::Color::End;
|
||||
buf << Config.empty_tags_color
|
||||
<< Config.empty_tag
|
||||
<< NC::FormattedColor::End(Config.empty_tags_color);
|
||||
else
|
||||
buf << tag;
|
||||
}
|
||||
|
||||
inline NC::Buffer ShowTag(const std::string &tag)
|
||||
{
|
||||
NC::Buffer result;
|
||||
ShowTag(result, tag);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline const char *withErrors(bool success)
|
||||
{
|
||||
return success ? "" : " " "(with errors)";
|
||||
|
||||
@@ -93,7 +93,8 @@ void ArtistInfo::beautifyOutput(NC::Scrollpad &w)
|
||||
{
|
||||
w.setProperties(NC::Format::Bold, "\n\nSimilar artists:\n", NC::Format::NoBold, 0);
|
||||
w.setProperties(NC::Format::Bold, "\n\nSimilar tags:\n", NC::Format::NoBold, 0);
|
||||
w.setProperties(Config.color2, "\n * ", NC::Color::End, 0, boost::regex::literal);
|
||||
// FIXME
|
||||
//w.setProperties(Config.color2, "\n * ", NC::Color::End, 0, boost::regex::literal);
|
||||
}
|
||||
|
||||
Service::Result ArtistInfo::processData(const std::string &data)
|
||||
|
||||
@@ -347,7 +347,13 @@ void SearchEngine::runAction()
|
||||
found += 3; // don't count options inserted below
|
||||
w.insertSeparator(ResetButton+1);
|
||||
w.insertItem(ResetButton+2, SEItem(), NC::List::Properties::Bold | NC::List::Properties::Inactive);
|
||||
w.at(ResetButton+2).value().mkBuffer() << Config.color1 << "Search results: " << Config.color2 << "Found " << found << (found > 1 ? " songs" : " song") << NC::Color::Default;
|
||||
w.at(ResetButton+2).value().mkBuffer()
|
||||
<< Config.color1
|
||||
<< "Search results: "
|
||||
<< NC::FormattedColor::End(Config.color1)
|
||||
<< Config.color2
|
||||
<< "Found " << found << (found > 1 ? " songs" : " song")
|
||||
<< NC::FormattedColor::End(Config.color2);
|
||||
w.insertSeparator(ResetButton+3);
|
||||
markSongsInPlaylist(w);
|
||||
Statusbar::print("Searching finished");
|
||||
|
||||
@@ -95,11 +95,25 @@ void SongInfo::switchTo()
|
||||
|
||||
void SongInfo::PrepareSong(const MPD::Song &s)
|
||||
{
|
||||
w << NC::Format::Bold << Config.color1 << "Filename: " << NC::Format::NoBold << Config.color2 << s.getName() << '\n' << NC::Color::End;
|
||||
w << NC::Format::Bold << "Directory: " << NC::Format::NoBold << Config.color2;
|
||||
ShowTag(w, s.getDirectory());
|
||||
w << "\n\n" << NC::Color::End;
|
||||
w << NC::Format::Bold << "Length: " << NC::Format::NoBold << Config.color2 << s.getLength() << '\n' << NC::Color::End;
|
||||
auto print_key_value = [this](const char *key, const auto &value) {
|
||||
w << NC::Format::Bold
|
||||
<< Config.color1
|
||||
<< key
|
||||
<< ":"
|
||||
<< NC::FormattedColor::End(Config.color1)
|
||||
<< NC::Format::NoBold
|
||||
<< " "
|
||||
<< Config.color2
|
||||
<< value
|
||||
<< NC::FormattedColor::End(Config.color2)
|
||||
<< "\n";
|
||||
};
|
||||
|
||||
print_key_value("Filename", s.getName());
|
||||
print_key_value("Directory", ShowTag(s.getDirectory()));
|
||||
w << "\n";
|
||||
print_key_value("Length", s.getLength());
|
||||
|
||||
# ifdef HAVE_TAGLIB_H
|
||||
if (!Config.mpd_music_dir.empty() && !s.isStream())
|
||||
{
|
||||
@@ -110,31 +124,23 @@ void SongInfo::PrepareSong(const MPD::Song &s)
|
||||
TagLib::FileRef f(path_to_file.c_str());
|
||||
if (!f.isNull())
|
||||
{
|
||||
std::string channels;
|
||||
switch (f.audioProperties()->channels())
|
||||
{
|
||||
case 1:
|
||||
channels = "Mono";
|
||||
break;
|
||||
case 2:
|
||||
channels = "Stereo";
|
||||
break;
|
||||
default:
|
||||
channels = boost::lexical_cast<std::string>(f.audioProperties()->channels());
|
||||
break;
|
||||
}
|
||||
w << NC::Format::Bold << "Bitrate: " << NC::Format::NoBold << Config.color2 << f.audioProperties()->bitrate() << " kbps\n" << NC::Color::End;
|
||||
w << NC::Format::Bold << "Sample rate: " << NC::Format::NoBold << Config.color2 << f.audioProperties()->sampleRate() << " Hz\n" << NC::Color::End;
|
||||
w << NC::Format::Bold << "Channels: " << NC::Format::NoBold << Config.color2 << channels << NC::Color::End << "\n";
|
||||
print_key_value(
|
||||
"Bitrate",
|
||||
boost::lexical_cast<std::string>(f.audioProperties()->bitrate()) + " kbps");
|
||||
print_key_value(
|
||||
"Sample rate",
|
||||
boost::lexical_cast<std::string>(f.audioProperties()->sampleRate()) + " Hz");
|
||||
print_key_value("Channels", channelsToString(f.audioProperties()->channels()));
|
||||
|
||||
auto rginfo = Tags::readReplayGain(f.file());
|
||||
if (!rginfo.empty())
|
||||
{
|
||||
w << NC::Format::Bold << "\nReference loudness: " << NC::Format::NoBold << Config.color2 << rginfo.referenceLoudness() << NC::Color::End << "\n";
|
||||
w << NC::Format::Bold << "Track gain: " << NC::Format::NoBold << Config.color2 << rginfo.trackGain() << NC::Color::End << "\n";
|
||||
w << NC::Format::Bold << "Track peak: " << NC::Format::NoBold << Config.color2 << rginfo.trackPeak() << NC::Color::End << "\n";
|
||||
w << NC::Format::Bold << "Album gain: " << NC::Format::NoBold << Config.color2 << rginfo.albumGain() << NC::Color::End << "\n";
|
||||
w << NC::Format::Bold << "Album peak: " << NC::Format::NoBold << Config.color2 << rginfo.albumPeak() << NC::Color::End << "\n";
|
||||
w << "\n";
|
||||
print_key_value("Reference loudness", rginfo.referenceLoudness());
|
||||
print_key_value("Track gain", rginfo.trackGain());
|
||||
print_key_value("Track peak", rginfo.trackPeak());
|
||||
print_key_value("Album gain", rginfo.albumGain());
|
||||
print_key_value("Album peak", rginfo.albumPeak());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -143,7 +149,7 @@ void SongInfo::PrepareSong(const MPD::Song &s)
|
||||
|
||||
for (const Metadata *m = Tags; m->Name; ++m)
|
||||
{
|
||||
w << NC::Format::Bold << '\n' << m->Name << ": " << NC::Format::NoBold;
|
||||
w << NC::Format::Bold << "\n" << m->Name << ":" << NC::Format::NoBold << " ";
|
||||
ShowTag(w, s.getTags(m->Get));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,7 +551,11 @@ void TagEditor::runAction()
|
||||
*FParserLegend << "%C - comment\n\n";
|
||||
*FParserLegend << NC::Format::Bold << "Files:\n" << NC::Format::NoBold;
|
||||
for (auto it = EditedSongs.begin(); it != EditedSongs.end(); ++it)
|
||||
*FParserLegend << Config.color2 << " * " << NC::Color::End << (*it)->getName() << '\n';
|
||||
*FParserLegend << Config.color2
|
||||
<< " * "
|
||||
<< NC::FormattedColor::End(Config.color2)
|
||||
<< (*it)->getName()
|
||||
<< "\n";
|
||||
FParserLegend->flush();
|
||||
|
||||
if (!Patterns.empty())
|
||||
@@ -631,9 +635,14 @@ void TagEditor::runAction()
|
||||
}
|
||||
if (!FParserUsePreview)
|
||||
s.setNewName(new_file + extension);
|
||||
*FParserPreview << file << Config.color2 << " -> " << NC::Color::End;
|
||||
*FParserPreview << file
|
||||
<< Config.color2
|
||||
<< " -> "
|
||||
<< NC::FormattedColor::End(Config.color2);
|
||||
if (new_file.empty())
|
||||
*FParserPreview << Config.empty_tags_color << Config.empty_tag << NC::Color::End;
|
||||
*FParserPreview << Config.empty_tags_color
|
||||
<< Config.empty_tag
|
||||
<< NC::FormattedColor::End(Config.empty_tags_color);
|
||||
else
|
||||
*FParserPreview << new_file << extension;
|
||||
*FParserPreview << "\n\n";
|
||||
|
||||
@@ -208,41 +208,69 @@ bool TinyTagEditor::getTags()
|
||||
w.resizeList(24);
|
||||
|
||||
for (size_t i = 0; i < 7; ++i)
|
||||
w.at(i).setInactive(true);
|
||||
w[i].setInactive(true);
|
||||
|
||||
w.at(7).setSeparator(true);
|
||||
w.at(19).setSeparator(true);
|
||||
w.at(21).setSeparator(true);
|
||||
w[7].setSeparator(true);
|
||||
w[19].setSeparator(true);
|
||||
w[21].setSeparator(true);
|
||||
|
||||
if (!Tags::extendedSetSupported(f.file()))
|
||||
{
|
||||
w.at(10).setInactive(true);
|
||||
w[10].setInactive(true);
|
||||
for (size_t i = 15; i <= 17; ++i)
|
||||
w.at(i).setInactive(true);
|
||||
w[i].setInactive(true);
|
||||
}
|
||||
|
||||
w.highlight(8);
|
||||
|
||||
w.at(0).value() << NC::Format::Bold << Config.color1 << "Song name: " << NC::Format::NoBold << Config.color2 << itsEdited.getName() << NC::Color::End;
|
||||
w.at(1).value() << NC::Format::Bold << Config.color1 << "Location in DB: " << NC::Format::NoBold << Config.color2;
|
||||
ShowTag(w.at(1).value(), itsEdited.getDirectory());
|
||||
w.at(1).value() << NC::Color::End;
|
||||
w.at(3).value() << NC::Format::Bold << Config.color1 << "Length: " << NC::Format::NoBold << Config.color2 << itsEdited.getLength() << NC::Color::End;
|
||||
w.at(4).value() << NC::Format::Bold << Config.color1 << "Bitrate: " << NC::Format::NoBold << Config.color2 << f.audioProperties()->bitrate() << " kbps" << NC::Color::End;
|
||||
w.at(5).value() << NC::Format::Bold << Config.color1 << "Sample rate: " << NC::Format::NoBold << Config.color2 << f.audioProperties()->sampleRate() << " Hz" << NC::Color::End;
|
||||
w.at(6).value() << NC::Format::Bold << Config.color1 << "Channels: " << NC::Format::NoBold << Config.color2 << (f.audioProperties()->channels() == 1 ? "Mono" : "Stereo") << NC::Color::Default;
|
||||
|
||||
auto print_key_value = [this](NC::Buffer &buf, const char *key, const auto &value) {
|
||||
buf << NC::Format::Bold
|
||||
<< Config.color1
|
||||
<< key
|
||||
<< ":"
|
||||
<< NC::FormattedColor::End(Config.color1)
|
||||
<< NC::Format::NoBold
|
||||
<< " "
|
||||
<< Config.color2
|
||||
<< value
|
||||
<< NC::FormattedColor::End(Config.color2);
|
||||
};
|
||||
|
||||
print_key_value(w[0].value(), "Filename", itsEdited.getName());
|
||||
print_key_value(w[1].value(), "Directory", ShowTag(itsEdited.getDirectory()));
|
||||
print_key_value(w[3].value(), "Length", itsEdited.getLength());
|
||||
print_key_value(
|
||||
w[4].value(),
|
||||
"Bitrate",
|
||||
boost::lexical_cast<std::string>(f.audioProperties()->bitrate()) + " kbps");
|
||||
print_key_value(
|
||||
w[5].value(),
|
||||
"Sample rate",
|
||||
boost::lexical_cast<std::string>(f.audioProperties()->sampleRate()) + " Hz");
|
||||
print_key_value(
|
||||
w[6].value(),
|
||||
"Channels",
|
||||
channelsToString(f.audioProperties()->channels()));
|
||||
|
||||
unsigned pos = 8;
|
||||
for (const SongInfo::Metadata *m = SongInfo::Tags; m->Name; ++m, ++pos)
|
||||
{
|
||||
w.at(pos).value() << NC::Format::Bold << m->Name << ":" << NC::Format::NoBold << ' ';
|
||||
ShowTag(w.at(pos).value(), itsEdited.getTags(m->Get));
|
||||
w[pos].value() << NC::Format::Bold
|
||||
<< m->Name
|
||||
<< ":"
|
||||
<< NC::Format::NoBold
|
||||
<< " ";
|
||||
ShowTag(w[pos].value(), itsEdited.getTags(m->Get));
|
||||
}
|
||||
|
||||
w.at(20).value() << NC::Format::Bold << "Filename:" << NC::Format::NoBold << ' ' << itsEdited.getName();
|
||||
w[20].value() << NC::Format::Bold
|
||||
<< "Filename:"
|
||||
<< NC::Format::NoBold
|
||||
<< " "
|
||||
<< itsEdited.getName();
|
||||
|
||||
w.at(22).value() << "Save";
|
||||
w.at(23).value() << "Cancel";
|
||||
w[22].value() << "Save";
|
||||
w[23].value() << "Cancel";
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,9 +51,10 @@ namespace {
|
||||
|
||||
const int fps = 25;
|
||||
|
||||
// toColor: a scaling function for coloring. For numbers 0 to max this function returns
|
||||
// a coloring from the lowest color to the highest, and colors will not loop from 0 to max.
|
||||
const NC::Color &toColor(size_t number, size_t max, bool wrap = true)
|
||||
// toColor: a scaling function for coloring. For numbers 0 to max this function
|
||||
// returns a coloring from the lowest color to the highest, and colors will not
|
||||
// loop from 0 to max.
|
||||
const NC::FormattedColor &toColor(size_t number, size_t max, bool wrap = true)
|
||||
{
|
||||
const auto colors_size = Config.visualizer_colors.size();
|
||||
const auto index = (number * colors_size) / max;
|
||||
@@ -216,10 +217,11 @@ void Visualizer::DrawSoundWave(int16_t *buf, ssize_t samples, size_t y_offset, s
|
||||
return;
|
||||
|
||||
auto draw_point = [&](size_t x, int32_t y) {
|
||||
auto c = toColor(std::abs(y), half_height, false);
|
||||
w << NC::XY(x, base_y+y)
|
||||
<< toColor(std::abs(y), half_height, false)
|
||||
<< Config.visualizer_chars[0]
|
||||
<< NC::Color::End;
|
||||
<< c
|
||||
<< Config.visualizer_chars[0]
|
||||
<< NC::FormattedColor::End(c);
|
||||
};
|
||||
|
||||
int32_t point_y, prev_point_y = 0;
|
||||
@@ -263,9 +265,10 @@ void Visualizer::DrawSoundWaveStereo(int16_t *buf_left, int16_t *buf_right, ssiz
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
// DrawSoundWaveFill: This visualizer is very similar to DrawSoundWave, but instead of
|
||||
// a single line the entire height is filled. In stereo mode, the top half of the screen
|
||||
// is dedicated to the right channel, the bottom the left channel.
|
||||
// DrawSoundWaveFill: This visualizer is very similar to DrawSoundWave, but
|
||||
// instead of a single line the entire height is filled. In stereo mode, the top
|
||||
// half of the screen is dedicated to the right channel, the bottom the left
|
||||
// channel.
|
||||
void Visualizer::DrawSoundWaveFill(int16_t *buf, ssize_t samples, size_t y_offset, size_t height)
|
||||
{
|
||||
// if right channel is drawn, bars descend from the top to the bottom
|
||||
@@ -291,11 +294,12 @@ void Visualizer::DrawSoundWaveFill(int16_t *buf, ssize_t samples, size_t y_offse
|
||||
|
||||
for (int32_t j = 0; j < point_y; ++j)
|
||||
{
|
||||
auto c = toColor(j, height);
|
||||
size_t y = flipped ? y_offset+j : y_offset+height-j-1;
|
||||
w << NC::XY(x, y)
|
||||
<< toColor(j, height)
|
||||
<< Config.visualizer_chars[1]
|
||||
<< NC::Color::End;
|
||||
<< c
|
||||
<< Config.visualizer_chars[1]
|
||||
<< NC::FormattedColor::End(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -308,13 +312,13 @@ void Visualizer::DrawSoundWaveFillStereo(int16_t *buf_left, int16_t *buf_right,
|
||||
|
||||
/**********************************************************************/
|
||||
|
||||
// draws the sound wave as an ellipse with origin in the center of the screen
|
||||
// Draws the sound wave as an ellipse with origin in the center of the screen.
|
||||
void Visualizer::DrawSoundEllipse(int16_t *buf, ssize_t samples, size_t, size_t height)
|
||||
{
|
||||
const size_t half_width = w.getWidth()/2;
|
||||
const size_t half_height = height/2;
|
||||
|
||||
// make it so that the loop goes around the ellipse exactly once
|
||||
// Make it so that the loop goes around the ellipse exactly once.
|
||||
const double deg_multiplier = 2*boost::math::constants::pi<double>()/samples;
|
||||
|
||||
int32_t x, y;
|
||||
@@ -325,30 +329,33 @@ void Visualizer::DrawSoundEllipse(int16_t *buf, ssize_t samples, size_t, size_t
|
||||
y = half_height * std::sin(i*deg_multiplier);
|
||||
max_radius = sqrt(x*x + y*y);
|
||||
|
||||
// calculate the distance of the sample from the center,
|
||||
// where 0 is the center of the ellipse and 1 is its border
|
||||
// Calculate the distance of the sample from the center, where 0 is the
|
||||
// center of the ellipse and 1 is its border.
|
||||
radius = std::abs(buf[i]);
|
||||
radius /= 32768.0;
|
||||
|
||||
// appropriately scale the position
|
||||
// Appropriately scale the position.
|
||||
x *= radius;
|
||||
y *= radius;
|
||||
|
||||
auto c = toColor(sqrt(x*x + y*y), max_radius, false);
|
||||
w << NC::XY(half_width + x, half_height + y)
|
||||
<< toColor(sqrt(x*x + y*y), max_radius, false)
|
||||
<< Config.visualizer_chars[0]
|
||||
<< NC::Color::End;
|
||||
<< c
|
||||
<< Config.visualizer_chars[0]
|
||||
<< NC::FormattedColor::End(c);
|
||||
}
|
||||
}
|
||||
|
||||
// DrawSoundEllipseStereo: This visualizer only works in stereo. The colors form concentric
|
||||
// rings originating from the center (width/2, height/2). For any given point, the width is
|
||||
// scaled with the left channel and height is scaled with the right channel. For example,
|
||||
// if a song is entirely in the right channel, then it would just be a vertical line.
|
||||
// DrawSoundEllipseStereo: This visualizer only works in stereo. The colors form
|
||||
// concentric rings originating from the center (width/2, height/2). For any
|
||||
// given point, the width is scaled with the left channel and height is scaled
|
||||
// with the right channel. For example, if a song is entirely in the right
|
||||
// channel, then it would just be a vertical line.
|
||||
//
|
||||
// Since every font/terminal is different, the visualizer is never a perfect circle. This
|
||||
// visualizer assume the font height is twice the length of the font's width. If the font
|
||||
// is skinner or wider than this, instead of a circle it will be an ellipse.
|
||||
// Since every font/terminal is different, the visualizer is never a perfect
|
||||
// circle. This visualizer assume the font height is twice the length of the
|
||||
// font's width. If the font is skinner or wider than this, instead of a circle
|
||||
// it will be an ellipse.
|
||||
void Visualizer::DrawSoundEllipseStereo(int16_t *buf_left, int16_t *buf_right, ssize_t samples, size_t half_height)
|
||||
{
|
||||
const size_t width = w.getWidth();
|
||||
@@ -365,14 +372,16 @@ void Visualizer::DrawSoundEllipseStereo(int16_t *buf_left, int16_t *buf_right, s
|
||||
x = buf_left[i]/32768.0 * (buf_left[i] < 0 ? left_half_width : right_half_width);
|
||||
y = buf_right[i]/32768.0 * (buf_right[i] < 0 ? top_half_height : bottom_half_height);
|
||||
|
||||
// The arguments to the toColor function roughly follow a circle equation where
|
||||
// the center is not centered around (0,0). For example (x - w)^2 + (y-h)+2 = r^2
|
||||
// centers the circle around the point (w,h). Because fonts are not all the same
|
||||
// size, this will not always generate a perfect circle.
|
||||
w << toColor(sqrt(x*x + 4*y*y), radius)
|
||||
<< NC::XY(left_half_width + x, top_half_height + y)
|
||||
<< Config.visualizer_chars[1]
|
||||
<< NC::Color::End;
|
||||
// The arguments to the toColor function roughly follow a circle equation
|
||||
// where the center is not centered around (0,0). For example (x - w)^2 +
|
||||
// (y-h)+2 = r^2 centers the circle around the point (w,h). Because fonts
|
||||
// are not all the same size, this will not always generate a perfect
|
||||
// circle.
|
||||
auto c = toColor(sqrt(x*x + 4*y*y), radius);
|
||||
w << NC::XY(left_half_width + x, top_half_height + y)
|
||||
<< c
|
||||
<< Config.visualizer_chars[1]
|
||||
<< NC::FormattedColor::End(c);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,7 +390,7 @@ void Visualizer::DrawSoundEllipseStereo(int16_t *buf_left, int16_t *buf_right, s
|
||||
#ifdef HAVE_FFTW3_H
|
||||
void Visualizer::DrawFrequencySpectrum(int16_t *buf, ssize_t samples, size_t y_offset, size_t height)
|
||||
{
|
||||
// if right channel is drawn, bars descend from the top to the bottom
|
||||
// If right channel is drawn, bars descend from the top to the bottom.
|
||||
const bool flipped = y_offset > 0;
|
||||
|
||||
// copy samples to fftw input array
|
||||
@@ -389,7 +398,7 @@ void Visualizer::DrawFrequencySpectrum(int16_t *buf, ssize_t samples, size_t y_o
|
||||
m_fftw_input[i] = i < samples ? buf[i] : 0;
|
||||
fftw_execute(m_fftw_plan);
|
||||
|
||||
// count magnitude of each frequency and scale it to fit the screen
|
||||
// Count magnitude of each frequency and scale it to fit the screen.
|
||||
for (size_t i = 0; i < m_fftw_results; ++i)
|
||||
m_freq_magnitudes[i] = sqrt(
|
||||
m_fftw_output[i][0]*m_fftw_output[i][0]
|
||||
@@ -397,7 +406,7 @@ void Visualizer::DrawFrequencySpectrum(int16_t *buf, ssize_t samples, size_t y_o
|
||||
)/2e4*height;
|
||||
|
||||
const size_t win_width = w.getWidth();
|
||||
// cut bandwidth a little to achieve better look
|
||||
// Cut bandwidth a little to achieve better look.
|
||||
const double bins_per_bar = m_fftw_results/win_width * 7/10;
|
||||
double bar_height;
|
||||
size_t bar_bound_height;
|
||||
@@ -406,19 +415,20 @@ void Visualizer::DrawFrequencySpectrum(int16_t *buf, ssize_t samples, size_t y_o
|
||||
bar_height = 0;
|
||||
for (int j = 0; j < bins_per_bar; ++j)
|
||||
bar_height += m_freq_magnitudes[x*bins_per_bar+j];
|
||||
// buff higher frequencies
|
||||
// Buff higher frequencies.
|
||||
bar_height *= log2(2 + x) * 100.0/win_width;
|
||||
// moderately normalize the heights
|
||||
// Moderately normalize the heights.
|
||||
bar_height = pow(bar_height, 0.5);
|
||||
|
||||
bar_bound_height = std::min(std::size_t(bar_height/bins_per_bar), height);
|
||||
for (size_t j = 0; j < bar_bound_height; ++j)
|
||||
{
|
||||
size_t y = flipped ? y_offset+j : y_offset+height-j-1;
|
||||
auto c = toColor(j, height);
|
||||
w << NC::XY(x, y)
|
||||
<< toColor(j, height)
|
||||
<< Config.visualizer_chars[1]
|
||||
<< NC::Color::End;
|
||||
<< c
|
||||
<< Config.visualizer_chars[1]
|
||||
<< NC::FormattedColor::End(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -495,5 +505,3 @@ void Visualizer::ResetAutoScaleMultiplier()
|
||||
}
|
||||
|
||||
#endif // ENABLE_VISUALIZER
|
||||
|
||||
/* vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab : */
|
||||
|
||||
@@ -177,11 +177,14 @@ NC::Buffer buffer(const std::string &v)
|
||||
return result;
|
||||
}
|
||||
|
||||
void deprecated(const char *option, double version_removal)
|
||||
void deprecated(const char *option, double version_removal, const char *advice)
|
||||
{
|
||||
std::cerr << "WARNING: Variable '" << option
|
||||
<< "' is deprecated and will be removed in "
|
||||
<< version_removal << "\n";
|
||||
<< version_removal;
|
||||
if (advice)
|
||||
std::cerr << " (" << advice << ")";
|
||||
std::cerr << ".\n";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -192,7 +195,17 @@ bool Configuration::read(const std::vector<std::string> &config_paths, bool igno
|
||||
|
||||
p.add<void>("visualizer_sample_multiplier", nullptr, "", [](std::string v) {
|
||||
if (!v.empty())
|
||||
deprecated("visualizer_sample_multiplier", 0.9);
|
||||
deprecated(
|
||||
"visualizer_sample_multiplier",
|
||||
0.9,
|
||||
"visualizer scales automatically");
|
||||
});
|
||||
p.add<void>("progressbar_boldness", nullptr, "", [](std::string v) {
|
||||
if (!v.empty())
|
||||
deprecated(
|
||||
"progressbar_boldness",
|
||||
0.9,
|
||||
"use extended progressbar_color and progressbar_elapsed_color instead");
|
||||
});
|
||||
|
||||
// keep the same order of variables as in configuration file
|
||||
@@ -224,7 +237,7 @@ bool Configuration::read(const std::vector<std::string> &config_paths, bool igno
|
||||
return result;
|
||||
});
|
||||
p.add("visualizer_color", &visualizer_colors,
|
||||
"blue, cyan, green, yellow, magenta, red", list_of<NC::Color>);
|
||||
"blue, cyan, green, yellow, magenta, red", list_of<NC::FormattedColor>);
|
||||
p.add("system_encoding", &system_encoding, "", [](std::string encoding) {
|
||||
#ifdef HAVE_LANGINFO_H
|
||||
// try to autodetect system encoding
|
||||
@@ -334,7 +347,6 @@ bool Configuration::read(const std::vector<std::string> &config_paths, bool igno
|
||||
result.resize(3);
|
||||
return result;
|
||||
});
|
||||
p.add("progressbar_boldness", &progressbar_boldness, "yes", yes_no);
|
||||
p.add("default_place_to_search_in", &search_in_db, "database", [](std::string v) {
|
||||
if (v == "database")
|
||||
return true;
|
||||
@@ -488,15 +500,15 @@ bool Configuration::read(const std::vector<std::string> &config_paths, bool igno
|
||||
p.add("header_window_color", &header_color, "default");
|
||||
p.add("volume_color", &volume_color, "default");
|
||||
p.add("state_line_color", &state_line_color, "default");
|
||||
p.add("state_flags_color", &state_flags_color, "default");
|
||||
p.add("state_flags_color", &state_flags_color, "default:b");
|
||||
p.add("main_window_color", &main_color, "yellow");
|
||||
p.add("color1", &color1, "white");
|
||||
p.add("color2", &color2, "green");
|
||||
p.add("main_window_highlight_color", &main_highlight_color, "yellow");
|
||||
p.add("progressbar_color", &progressbar_color, "black");
|
||||
p.add("progressbar_elapsed_color", &progressbar_elapsed_color, "green");
|
||||
p.add("progressbar_color", &progressbar_color, "black:b");
|
||||
p.add("progressbar_elapsed_color", &progressbar_elapsed_color, "green:b");
|
||||
p.add("statusbar_color", &statusbar_color, "default");
|
||||
p.add("alternative_ui_separator_color", &alternative_ui_separator_color, "black");
|
||||
p.add("alternative_ui_separator_color", &alternative_ui_separator_color, "black:b");
|
||||
p.add("active_column_color", &active_column_color, "red");
|
||||
p.add("window_border_color", &window_border, "green", verbose_lexical_cast<NC::Color>);
|
||||
p.add("active_window_border", &active_window_border, "red",
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <vector>
|
||||
#include <mpd/client.h>
|
||||
|
||||
#include "curses/formatted_color.h"
|
||||
#include "curses/strbuffer.h"
|
||||
#include "enums.h"
|
||||
#include "format.h"
|
||||
@@ -98,22 +99,23 @@ struct Configuration
|
||||
NC::Buffer now_playing_suffix;
|
||||
NC::Buffer modified_item_prefix;
|
||||
|
||||
NC::Color color1;
|
||||
NC::Color color2;
|
||||
NC::Color empty_tags_color;
|
||||
NC::Color header_color;
|
||||
NC::Color volume_color;
|
||||
NC::Color state_line_color;
|
||||
NC::Color state_flags_color;
|
||||
NC::Color main_color;
|
||||
NC::Color main_highlight_color;
|
||||
NC::Color progressbar_color;
|
||||
NC::Color progressbar_elapsed_color;
|
||||
NC::Color statusbar_color;
|
||||
NC::Color alternative_ui_separator_color;
|
||||
NC::Color main_highlight_color;
|
||||
NC::Color active_column_color;
|
||||
|
||||
std::vector<NC::Color> visualizer_colors;
|
||||
NC::FormattedColor color1;
|
||||
NC::FormattedColor color2;
|
||||
NC::FormattedColor empty_tags_color;
|
||||
NC::FormattedColor volume_color;
|
||||
NC::FormattedColor state_line_color;
|
||||
NC::FormattedColor state_flags_color;
|
||||
NC::FormattedColor progressbar_color;
|
||||
NC::FormattedColor progressbar_elapsed_color;
|
||||
NC::FormattedColor alternative_ui_separator_color;
|
||||
|
||||
std::vector<NC::FormattedColor> visualizer_colors;
|
||||
VisualizerType visualizer_type;
|
||||
|
||||
NC::Border window_border;
|
||||
@@ -166,7 +168,6 @@ struct Configuration
|
||||
bool generate_win32_compatible_filenames;
|
||||
bool ask_for_locked_screen_width_part;
|
||||
bool allow_for_physical_item_deletion;
|
||||
bool progressbar_boldness;
|
||||
bool startup_slave_screen_focus;
|
||||
|
||||
unsigned mpd_connection_timeout;
|
||||
|
||||
@@ -687,7 +687,10 @@ void Status::Changes::elapsedTime(bool update_elapsed)
|
||||
*wHeader << NC::XY(second_start, 1);
|
||||
writeCyclicBuffer(second, *wHeader, second_line_scroll_begin, COLS-ps.length()-8-2, L" ** ");
|
||||
|
||||
*wHeader << NC::XY(wHeader->getWidth()-VolumeState.length(), 0) << Config.volume_color << VolumeState << NC::Color::End;
|
||||
*wHeader << NC::XY(wHeader->getWidth()-VolumeState.length(), 0)
|
||||
<< Config.volume_color
|
||||
<< VolumeState
|
||||
<< NC::FormattedColor::End(Config.volume_color);
|
||||
|
||||
flags();
|
||||
}
|
||||
@@ -719,11 +722,14 @@ void Status::Changes::flags()
|
||||
|
||||
*wHeader << Config.state_line_color;
|
||||
mvwhline(wHeader->raw(), 1, 0, 0, COLS);
|
||||
*wHeader << NC::FormattedColor::End(Config.state_line_color);
|
||||
|
||||
if (!switch_state.empty())
|
||||
*wHeader << NC::XY(COLS-switch_state.length()-3, 1) << "["
|
||||
*wHeader << NC::XY(COLS-switch_state.length()-3, 1)
|
||||
<< "["
|
||||
<< Config.state_flags_color
|
||||
<< NC::Format::Bold << switch_state << NC::Format::NoBold
|
||||
<< NC::Color::End
|
||||
<< switch_state
|
||||
<< NC::FormattedColor::End(Config.state_flags_color)
|
||||
<< "]";
|
||||
break;
|
||||
case Design::Alternative:
|
||||
@@ -735,12 +741,15 @@ void Status::Changes::flags()
|
||||
switch_state += m_crossfade ? m_crossfade : '-';
|
||||
switch_state += m_db_updating ? m_db_updating : '-';
|
||||
switch_state += ']';
|
||||
*wHeader << NC::XY(COLS-switch_state.length(), 1) << NC::Format::Bold << Config.state_flags_color << switch_state << NC::Color::End << NC::Format::NoBold;
|
||||
*wHeader << NC::XY(COLS-switch_state.length(), 1)
|
||||
<< Config.state_flags_color
|
||||
<< switch_state
|
||||
<< NC::FormattedColor::End(Config.state_flags_color);
|
||||
if (!Config.header_visibility) // in this case also draw separator
|
||||
{
|
||||
*wHeader << NC::Format::Bold << Config.alternative_ui_separator_color;
|
||||
*wHeader << Config.alternative_ui_separator_color;
|
||||
mvwhline(wHeader->raw(), 2, 0, 0, COLS);
|
||||
*wHeader << NC::Color::End << NC::Format::NoBold;
|
||||
*wHeader << NC::FormattedColor::End(Config.alternative_ui_separator_color);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -749,7 +758,8 @@ void Status::Changes::flags()
|
||||
|
||||
void Status::Changes::mixer()
|
||||
{
|
||||
if (!Config.display_volume_level || (!Config.header_visibility && Config.design == Design::Classic))
|
||||
if (!Config.display_volume_level
|
||||
|| (!Config.header_visibility && Config.design == Design::Classic))
|
||||
return;
|
||||
|
||||
switch (Config.design)
|
||||
@@ -768,9 +778,10 @@ void Status::Changes::mixer()
|
||||
VolumeState += boost::lexical_cast<std::string>(m_volume);
|
||||
VolumeState += "%";
|
||||
}
|
||||
*wHeader << Config.volume_color;
|
||||
*wHeader << NC::XY(wHeader->getWidth()-VolumeState.length(), 0) << VolumeState;
|
||||
*wHeader << NC::Color::End;
|
||||
*wHeader << NC::XY(wHeader->getWidth()-VolumeState.length(), 0)
|
||||
<< Config.volume_color
|
||||
<< VolumeState
|
||||
<< NC::FormattedColor::End(Config.volume_color);
|
||||
wHeader->refresh();
|
||||
}
|
||||
|
||||
|
||||
@@ -59,8 +59,6 @@ void Progressbar::draw(unsigned int elapsed, unsigned int time)
|
||||
{
|
||||
unsigned pb_width = wFooter->getWidth();
|
||||
unsigned howlong = time ? pb_width*elapsed/time : 0;
|
||||
if (Config.progressbar_boldness)
|
||||
*wFooter << NC::Format::Bold;
|
||||
*wFooter << Config.progressbar_color;
|
||||
if (Config.progressbar[2] != '\0')
|
||||
{
|
||||
@@ -71,6 +69,7 @@ void Progressbar::draw(unsigned int elapsed, unsigned int time)
|
||||
}
|
||||
else
|
||||
mvwhline(wFooter->raw(), 0, 0, 0, pb_width);
|
||||
*wFooter << NC::FormattedColor::End(Config.progressbar_color);
|
||||
if (time)
|
||||
{
|
||||
*wFooter << Config.progressbar_elapsed_color;
|
||||
@@ -79,11 +78,8 @@ void Progressbar::draw(unsigned int elapsed, unsigned int time)
|
||||
*wFooter << Config.progressbar[0];
|
||||
if (howlong < wFooter->getWidth())
|
||||
*wFooter << Config.progressbar[1];
|
||||
*wFooter << NC::Color::End;
|
||||
*wFooter << NC::FormattedColor::End(Config.progressbar_elapsed_color);
|
||||
}
|
||||
*wFooter << NC::Color::End;
|
||||
if (Config.progressbar_boldness)
|
||||
*wFooter << NC::Format::NoBold;
|
||||
}
|
||||
|
||||
Statusbar::ScopedLock::ScopedLock() noexcept
|
||||
|
||||
@@ -43,20 +43,28 @@ void drawHeader()
|
||||
switch (Config.design)
|
||||
{
|
||||
case Design::Classic:
|
||||
*wHeader << NC::XY(0, 0) << NC::TermManip::ClearToEOL << NC::Format::Bold << myScreen->title() << NC::Format::NoBold;
|
||||
*wHeader << Config.volume_color;
|
||||
*wHeader << NC::XY(wHeader->getWidth()-VolumeState.length(), 0) << VolumeState;
|
||||
*wHeader << NC::Color::End;
|
||||
*wHeader << NC::XY(0, 0)
|
||||
<< NC::TermManip::ClearToEOL
|
||||
<< NC::Format::Bold
|
||||
<< myScreen->title()
|
||||
<< NC::Format::NoBold
|
||||
<< NC::XY(wHeader->getWidth()-VolumeState.length(), 0)
|
||||
<< Config.volume_color
|
||||
<< VolumeState
|
||||
<< NC::FormattedColor::End(Config.volume_color);
|
||||
break;
|
||||
case Design::Alternative:
|
||||
std::wstring title = myScreen->title();
|
||||
*wHeader << NC::XY(0, 3) << NC::TermManip::ClearToEOL;
|
||||
*wHeader << NC::Format::Bold << Config.alternative_ui_separator_color;
|
||||
*wHeader << NC::XY(0, 3)
|
||||
<< NC::TermManip::ClearToEOL
|
||||
<< Config.alternative_ui_separator_color;
|
||||
mvwhline(wHeader->raw(), 2, 0, 0, COLS);
|
||||
mvwhline(wHeader->raw(), 4, 0, 0, COLS);
|
||||
*wHeader << NC::XY((COLS-wideLength(title))/2, 3);
|
||||
*wHeader << Config.header_color << title << NC::Color::End;
|
||||
*wHeader << NC::Color::End << NC::Format::NoBold;
|
||||
*wHeader << NC::FormattedColor::End(Config.alternative_ui_separator_color)
|
||||
<< NC::XY((COLS-wideLength(title))/2, 3)
|
||||
<< NC::Format::Bold
|
||||
<< title
|
||||
<< NC::Format::NoBold;
|
||||
break;
|
||||
}
|
||||
wHeader->refresh();
|
||||
|
||||
@@ -18,9 +18,23 @@
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
|
||||
***************************************************************************/
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <cassert>
|
||||
#include "utility/type_conversions.h"
|
||||
|
||||
std::string channelsToString(int channels)
|
||||
{
|
||||
switch (channels)
|
||||
{
|
||||
case 1:
|
||||
return "Mono";
|
||||
case 2:
|
||||
return "Stereo";
|
||||
default:
|
||||
return boost::lexical_cast<std::string>(channels);
|
||||
}
|
||||
}
|
||||
|
||||
NC::Color charToColor(char c)
|
||||
{
|
||||
switch (c)
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
#include "mutable_song.h"
|
||||
#include "enums.h"
|
||||
|
||||
std::string channelsToString(int channels);
|
||||
|
||||
NC::Color charToColor(char c);
|
||||
|
||||
std::string tagTypeToString(mpd_tag_type tag);
|
||||
|
||||
Reference in New Issue
Block a user