Support attaching format information to selected color variables

This commit is contained in:
Andrzej Rybczak
2016-12-22 16:31:41 +01:00
parent 9c13827b62
commit a488c2d89d
22 changed files with 492 additions and 175 deletions

View File

@@ -328,8 +328,6 @@
## ##
#progressbar_look = => #progressbar_look = =>
# #
#progressbar_boldness = yes
#
## Available values: database, playlist. ## Available values: database, playlist.
## ##
#default_place_to_search_in = database #default_place_to_search_in = database
@@ -496,6 +494,15 @@
## the bottom of the help screen for list of available colors ## the bottom of the help screen for list of available colors
## and their numerical values. ## 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 ## Note: due to technical limitations of ncurses, if 256 colors
## are used, it is possible to either use only the colors with ## 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, ## default background color, or all pairs from 1_1 up to 254_127,
@@ -512,7 +519,7 @@
# #
#state_line_color = default #state_line_color = default
# #
#state_flags_color = default #state_flags_color = default:b
# #
#main_window_color = yellow #main_window_color = yellow
# #
@@ -522,13 +529,13 @@
# #
#main_window_highlight_color = yellow #main_window_highlight_color = yellow
# #
#progressbar_color = black #progressbar_color = black:b
# #
#progressbar_elapsed_color = green #progressbar_elapsed_color = green:b
# #
#statusbar_color = default #statusbar_color = default
# #
#alternative_ui_separator_color = black #alternative_ui_separator_color = black:b
# #
#active_column_color = red #active_column_color = red
# #

View File

@@ -204,9 +204,6 @@ If enabled, currently highlighted position in the list will be always centered.
.B progressbar_look = TEXT .B progressbar_look = TEXT
This variable defines the look of progressbar. Note that it has to be exactly two or three characters long. This variable defines the look of progressbar. Note that it has to be exactly two or three characters long.
.TP .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 .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. If set to "playlist", Search engine will perform searching in current MPD playlist rather than in music database.
.TP .TP

View File

@@ -1,5 +1,6 @@
bin_PROGRAMS = ncmpcpp bin_PROGRAMS = ncmpcpp
ncmpcpp_SOURCES = \ ncmpcpp_SOURCES = \
curses/formatted_color.cpp \
curses/scrollpad.cpp \ curses/scrollpad.cpp \
curses/window.cpp \ curses/window.cpp \
screens/browser.cpp \ screens/browser.cpp \
@@ -57,6 +58,7 @@ INCLUDES= $(all_includes)
# the library search path. # the library search path.
ncmpcpp_LDFLAGS = $(all_libraries) ncmpcpp_LDFLAGS = $(all_libraries)
noinst_HEADERS = \ noinst_HEADERS = \
curses/formatted_color.h \
curses/menu.h \ curses/menu.h \
curses/menu_impl.h \ curses/menu_impl.h \
curses/scrollpad.h \ curses/scrollpad.h \

View 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;
}

View 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

View File

@@ -259,36 +259,67 @@ std::istream &operator>>(std::istream &is, Color &c)
} }
return result; 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") if (sc == "default")
c = Color::Default; c = Color::Default;
else if (sc == "end") else if (sc == "end")
c = Color::End; c = Color::End;
else else
{ {
short value = get_single_color(sc, false); short fg = get_single_color(sc, false);
if (value != -1) if (fg == -1)
c = Color(value, NC::Color::transparent); is.setstate(std::ios::failbit);
else // Check if there is background color
else if (!is.eof() && is.peek() == '_')
{ {
size_t underscore = sc.find('_'); is.get();
if (underscore != std::string::npos) sc = get_color(is);
{ short bg = get_single_color(sc, true);
short fg = get_single_color(sc.substr(0, underscore), false); if (bg == -1)
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.setstate(std::ios::failbit); is.setstate(std::ios::failbit);
else
c = Color(fg, bg);
} }
else
c = Color(fg, NC::Color::transparent);
} }
return is; 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 Mouse {
namespace { namespace {

View File

@@ -149,7 +149,7 @@ struct Color
static const short transparent; static const short transparent;
static const short previous; 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, Color(short foreground_value, short background_value,
bool is_default = false, bool is_end = false) bool is_default = false, bool is_end = false)
: m_impl(foreground_value, background_value, is_default, is_end) : m_impl(foreground_value, background_value, is_default, is_end)
@@ -201,6 +201,8 @@ enum class Format {
AltCharset, NoAltCharset AltCharset, NoAltCharset
}; };
NC::Format reverseFormat(NC::Format fmt);
/// This indicates how much the window has to be scrolled /// This indicates how much the window has to be scrolled
enum class Scroll { Up, Down, PageUp, PageDown, Home, End }; enum class Scroll { Up, Down, PageUp, PageDown, Home, End };

View File

@@ -349,7 +349,9 @@ void Display::Tags(NC::Menu<MPD::MutableSong> &menu)
menu << Charset::utf8ToLocale(s.getName()); menu << Charset::utf8ToLocale(s.getName());
else else
menu << Charset::utf8ToLocale(s.getName()) menu << Charset::utf8ToLocale(s.getName())
<< Config.color2 << " -> " << NC::Color::End << Config.color2
<< " -> "
<< NC::FormattedColor::End(Config.color2)
<< Charset::utf8ToLocale(s.getNewName()); << Charset::utf8ToLocale(s.getNewName());
} }
} }

View File

@@ -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")); 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()) 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 else
buf << tag; buf << tag;
} }
inline NC::Buffer ShowTag(const std::string &tag)
{
NC::Buffer result;
ShowTag(result, tag);
return result;
}
inline const char *withErrors(bool success) inline const char *withErrors(bool success)
{ {
return success ? "" : " " "(with errors)"; return success ? "" : " " "(with errors)";

View File

@@ -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 artists:\n", NC::Format::NoBold, 0);
w.setProperties(NC::Format::Bold, "\n\nSimilar tags:\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) Service::Result ArtistInfo::processData(const std::string &data)

View File

@@ -347,7 +347,13 @@ void SearchEngine::runAction()
found += 3; // don't count options inserted below found += 3; // don't count options inserted below
w.insertSeparator(ResetButton+1); w.insertSeparator(ResetButton+1);
w.insertItem(ResetButton+2, SEItem(), NC::List::Properties::Bold | NC::List::Properties::Inactive); 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); w.insertSeparator(ResetButton+3);
markSongsInPlaylist(w); markSongsInPlaylist(w);
Statusbar::print("Searching finished"); Statusbar::print("Searching finished");

View File

@@ -95,11 +95,25 @@ void SongInfo::switchTo()
void SongInfo::PrepareSong(const MPD::Song &s) 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; auto print_key_value = [this](const char *key, const auto &value) {
w << NC::Format::Bold << "Directory: " << NC::Format::NoBold << Config.color2; w << NC::Format::Bold
ShowTag(w, s.getDirectory()); << Config.color1
w << "\n\n" << NC::Color::End; << key
w << NC::Format::Bold << "Length: " << NC::Format::NoBold << Config.color2 << s.getLength() << '\n' << NC::Color::End; << ":"
<< 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 # ifdef HAVE_TAGLIB_H
if (!Config.mpd_music_dir.empty() && !s.isStream()) 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()); TagLib::FileRef f(path_to_file.c_str());
if (!f.isNull()) if (!f.isNull())
{ {
std::string channels; print_key_value(
switch (f.audioProperties()->channels()) "Bitrate",
{ boost::lexical_cast<std::string>(f.audioProperties()->bitrate()) + " kbps");
case 1: print_key_value(
channels = "Mono"; "Sample rate",
break; boost::lexical_cast<std::string>(f.audioProperties()->sampleRate()) + " Hz");
case 2: print_key_value("Channels", channelsToString(f.audioProperties()->channels()));
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";
auto rginfo = Tags::readReplayGain(f.file()); auto rginfo = Tags::readReplayGain(f.file());
if (!rginfo.empty()) if (!rginfo.empty())
{ {
w << NC::Format::Bold << "\nReference loudness: " << NC::Format::NoBold << Config.color2 << rginfo.referenceLoudness() << NC::Color::End << "\n"; w << "\n";
w << NC::Format::Bold << "Track gain: " << NC::Format::NoBold << Config.color2 << rginfo.trackGain() << NC::Color::End << "\n"; print_key_value("Reference loudness", rginfo.referenceLoudness());
w << NC::Format::Bold << "Track peak: " << NC::Format::NoBold << Config.color2 << rginfo.trackPeak() << NC::Color::End << "\n"; print_key_value("Track gain", rginfo.trackGain());
w << NC::Format::Bold << "Album gain: " << NC::Format::NoBold << Config.color2 << rginfo.albumGain() << NC::Color::End << "\n"; print_key_value("Track peak", rginfo.trackPeak());
w << NC::Format::Bold << "Album peak: " << NC::Format::NoBold << Config.color2 << rginfo.albumPeak() << NC::Color::End << "\n"; 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) 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)); ShowTag(w, s.getTags(m->Get));
} }
} }

View File

@@ -551,7 +551,11 @@ void TagEditor::runAction()
*FParserLegend << "%C - comment\n\n"; *FParserLegend << "%C - comment\n\n";
*FParserLegend << NC::Format::Bold << "Files:\n" << NC::Format::NoBold; *FParserLegend << NC::Format::Bold << "Files:\n" << NC::Format::NoBold;
for (auto it = EditedSongs.begin(); it != EditedSongs.end(); ++it) 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(); FParserLegend->flush();
if (!Patterns.empty()) if (!Patterns.empty())
@@ -631,9 +635,14 @@ void TagEditor::runAction()
} }
if (!FParserUsePreview) if (!FParserUsePreview)
s.setNewName(new_file + extension); 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()) 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 else
*FParserPreview << new_file << extension; *FParserPreview << new_file << extension;
*FParserPreview << "\n\n"; *FParserPreview << "\n\n";

View File

@@ -208,41 +208,69 @@ bool TinyTagEditor::getTags()
w.resizeList(24); w.resizeList(24);
for (size_t i = 0; i < 7; ++i) for (size_t i = 0; i < 7; ++i)
w.at(i).setInactive(true); w[i].setInactive(true);
w.at(7).setSeparator(true); w[7].setSeparator(true);
w.at(19).setSeparator(true); w[19].setSeparator(true);
w.at(21).setSeparator(true); w[21].setSeparator(true);
if (!Tags::extendedSetSupported(f.file())) if (!Tags::extendedSetSupported(f.file()))
{ {
w.at(10).setInactive(true); w[10].setInactive(true);
for (size_t i = 15; i <= 17; ++i) for (size_t i = 15; i <= 17; ++i)
w.at(i).setInactive(true); w[i].setInactive(true);
} }
w.highlight(8); w.highlight(8);
w.at(0).value() << NC::Format::Bold << Config.color1 << "Song name: " << NC::Format::NoBold << Config.color2 << itsEdited.getName() << NC::Color::End; auto print_key_value = [this](NC::Buffer &buf, const char *key, const auto &value) {
w.at(1).value() << NC::Format::Bold << Config.color1 << "Location in DB: " << NC::Format::NoBold << Config.color2; buf << NC::Format::Bold
ShowTag(w.at(1).value(), itsEdited.getDirectory()); << Config.color1
w.at(1).value() << NC::Color::End; << key
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; << NC::FormattedColor::End(Config.color1)
w.at(5).value() << NC::Format::Bold << Config.color1 << "Sample rate: " << NC::Format::NoBold << Config.color2 << f.audioProperties()->sampleRate() << " Hz" << NC::Color::End; << NC::Format::NoBold
w.at(6).value() << NC::Format::Bold << Config.color1 << "Channels: " << NC::Format::NoBold << Config.color2 << (f.audioProperties()->channels() == 1 ? "Mono" : "Stereo") << NC::Color::Default; << " "
<< 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; unsigned pos = 8;
for (const SongInfo::Metadata *m = SongInfo::Tags; m->Name; ++m, ++pos) for (const SongInfo::Metadata *m = SongInfo::Tags; m->Name; ++m, ++pos)
{ {
w.at(pos).value() << NC::Format::Bold << m->Name << ":" << NC::Format::NoBold << ' '; w[pos].value() << NC::Format::Bold
ShowTag(w.at(pos).value(), itsEdited.getTags(m->Get)); << 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[22].value() << "Save";
w.at(23).value() << "Cancel"; w[23].value() << "Cancel";
return true; return true;
} }

View File

@@ -51,9 +51,10 @@ namespace {
const int fps = 25; const int fps = 25;
// toColor: a scaling function for coloring. For numbers 0 to max this function returns // toColor: a scaling function for coloring. For numbers 0 to max this function
// a coloring from the lowest color to the highest, and colors will not loop from 0 to max. // returns a coloring from the lowest color to the highest, and colors will not
const NC::Color &toColor(size_t number, size_t max, bool wrap = true) // 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 colors_size = Config.visualizer_colors.size();
const auto index = (number * colors_size) / max; 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; return;
auto draw_point = [&](size_t x, int32_t y) { 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) w << NC::XY(x, base_y+y)
<< toColor(std::abs(y), half_height, false) << c
<< Config.visualizer_chars[0] << Config.visualizer_chars[0]
<< NC::Color::End; << NC::FormattedColor::End(c);
}; };
int32_t point_y, prev_point_y = 0; 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 // DrawSoundWaveFill: This visualizer is very similar to DrawSoundWave, but
// a single line the entire height is filled. In stereo mode, the top half of the screen // instead of a single line the entire height is filled. In stereo mode, the top
// is dedicated to the right channel, the bottom the left channel. // 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) 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 // 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) 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; size_t y = flipped ? y_offset+j : y_offset+height-j-1;
w << NC::XY(x, y) w << NC::XY(x, y)
<< toColor(j, height) << c
<< Config.visualizer_chars[1] << Config.visualizer_chars[1]
<< NC::Color::End; << 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) 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_width = w.getWidth()/2;
const size_t half_height = height/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; const double deg_multiplier = 2*boost::math::constants::pi<double>()/samples;
int32_t x, y; 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); y = half_height * std::sin(i*deg_multiplier);
max_radius = sqrt(x*x + y*y); max_radius = sqrt(x*x + y*y);
// calculate the distance of the sample from the center, // Calculate the distance of the sample from the center, where 0 is the
// where 0 is the center of the ellipse and 1 is its border // center of the ellipse and 1 is its border.
radius = std::abs(buf[i]); radius = std::abs(buf[i]);
radius /= 32768.0; radius /= 32768.0;
// appropriately scale the position // Appropriately scale the position.
x *= radius; x *= radius;
y *= radius; y *= radius;
auto c = toColor(sqrt(x*x + y*y), max_radius, false);
w << NC::XY(half_width + x, half_height + y) w << NC::XY(half_width + x, half_height + y)
<< toColor(sqrt(x*x + y*y), max_radius, false) << c
<< Config.visualizer_chars[0] << Config.visualizer_chars[0]
<< NC::Color::End; << NC::FormattedColor::End(c);
} }
} }
// DrawSoundEllipseStereo: This visualizer only works in stereo. The colors form concentric // DrawSoundEllipseStereo: This visualizer only works in stereo. The colors form
// rings originating from the center (width/2, height/2). For any given point, the width is // concentric rings originating from the center (width/2, height/2). For any
// scaled with the left channel and height is scaled with the right channel. For example, // given point, the width is scaled with the left channel and height is scaled
// if a song is entirely in the right channel, then it would just be a vertical line. // 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 // Since every font/terminal is different, the visualizer is never a perfect
// visualizer assume the font height is twice the length of the font's width. If the font // circle. This visualizer assume the font height is twice the length of the
// is skinner or wider than this, instead of a circle it will be an ellipse. // 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) void Visualizer::DrawSoundEllipseStereo(int16_t *buf_left, int16_t *buf_right, ssize_t samples, size_t half_height)
{ {
const size_t width = w.getWidth(); 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); 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); 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 arguments to the toColor function roughly follow a circle equation
// the center is not centered around (0,0). For example (x - w)^2 + (y-h)+2 = r^2 // where the center is not centered around (0,0). For example (x - w)^2 +
// centers the circle around the point (w,h). Because fonts are not all the same // (y-h)+2 = r^2 centers the circle around the point (w,h). Because fonts
// size, this will not always generate a perfect circle. // are not all the same size, this will not always generate a perfect
w << toColor(sqrt(x*x + 4*y*y), radius) // circle.
<< NC::XY(left_half_width + x, top_half_height + y) auto c = toColor(sqrt(x*x + 4*y*y), radius);
<< Config.visualizer_chars[1] w << NC::XY(left_half_width + x, top_half_height + y)
<< NC::Color::End; << 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 #ifdef HAVE_FFTW3_H
void Visualizer::DrawFrequencySpectrum(int16_t *buf, ssize_t samples, size_t y_offset, size_t height) 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; const bool flipped = y_offset > 0;
// copy samples to fftw input array // 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; m_fftw_input[i] = i < samples ? buf[i] : 0;
fftw_execute(m_fftw_plan); 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) for (size_t i = 0; i < m_fftw_results; ++i)
m_freq_magnitudes[i] = sqrt( m_freq_magnitudes[i] = sqrt(
m_fftw_output[i][0]*m_fftw_output[i][0] 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; )/2e4*height;
const size_t win_width = w.getWidth(); 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; const double bins_per_bar = m_fftw_results/win_width * 7/10;
double bar_height; double bar_height;
size_t bar_bound_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; bar_height = 0;
for (int j = 0; j < bins_per_bar; ++j) for (int j = 0; j < bins_per_bar; ++j)
bar_height += m_freq_magnitudes[x*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; 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_height = pow(bar_height, 0.5);
bar_bound_height = std::min(std::size_t(bar_height/bins_per_bar), height); bar_bound_height = std::min(std::size_t(bar_height/bins_per_bar), height);
for (size_t j = 0; j < bar_bound_height; ++j) for (size_t j = 0; j < bar_bound_height; ++j)
{ {
size_t y = flipped ? y_offset+j : y_offset+height-j-1; size_t y = flipped ? y_offset+j : y_offset+height-j-1;
auto c = toColor(j, height);
w << NC::XY(x, y) w << NC::XY(x, y)
<< toColor(j, height) << c
<< Config.visualizer_chars[1] << Config.visualizer_chars[1]
<< NC::Color::End; << NC::FormattedColor::End(c);
} }
} }
} }
@@ -495,5 +505,3 @@ void Visualizer::ResetAutoScaleMultiplier()
} }
#endif // ENABLE_VISUALIZER #endif // ENABLE_VISUALIZER
/* vim: set tabstop=4 softtabstop=4 shiftwidth=4 noexpandtab : */

View File

@@ -177,11 +177,14 @@ NC::Buffer buffer(const std::string &v)
return result; 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 std::cerr << "WARNING: Variable '" << option
<< "' is deprecated and will be removed in " << "' 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) { p.add<void>("visualizer_sample_multiplier", nullptr, "", [](std::string v) {
if (!v.empty()) 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 // 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; return result;
}); });
p.add("visualizer_color", &visualizer_colors, 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) { p.add("system_encoding", &system_encoding, "", [](std::string encoding) {
#ifdef HAVE_LANGINFO_H #ifdef HAVE_LANGINFO_H
// try to autodetect system encoding // try to autodetect system encoding
@@ -334,7 +347,6 @@ bool Configuration::read(const std::vector<std::string> &config_paths, bool igno
result.resize(3); result.resize(3);
return result; 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) { p.add("default_place_to_search_in", &search_in_db, "database", [](std::string v) {
if (v == "database") if (v == "database")
return true; 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("header_window_color", &header_color, "default");
p.add("volume_color", &volume_color, "default"); p.add("volume_color", &volume_color, "default");
p.add("state_line_color", &state_line_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("main_window_color", &main_color, "yellow");
p.add("color1", &color1, "white"); p.add("color1", &color1, "white");
p.add("color2", &color2, "green"); p.add("color2", &color2, "green");
p.add("main_window_highlight_color", &main_highlight_color, "yellow"); p.add("main_window_highlight_color", &main_highlight_color, "yellow");
p.add("progressbar_color", &progressbar_color, "black"); p.add("progressbar_color", &progressbar_color, "black:b");
p.add("progressbar_elapsed_color", &progressbar_elapsed_color, "green"); p.add("progressbar_elapsed_color", &progressbar_elapsed_color, "green:b");
p.add("statusbar_color", &statusbar_color, "default"); 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("active_column_color", &active_column_color, "red");
p.add("window_border_color", &window_border, "green", verbose_lexical_cast<NC::Color>); p.add("window_border_color", &window_border, "green", verbose_lexical_cast<NC::Color>);
p.add("active_window_border", &active_window_border, "red", p.add("active_window_border", &active_window_border, "red",

View File

@@ -28,6 +28,7 @@
#include <vector> #include <vector>
#include <mpd/client.h> #include <mpd/client.h>
#include "curses/formatted_color.h"
#include "curses/strbuffer.h" #include "curses/strbuffer.h"
#include "enums.h" #include "enums.h"
#include "format.h" #include "format.h"
@@ -98,22 +99,23 @@ struct Configuration
NC::Buffer now_playing_suffix; NC::Buffer now_playing_suffix;
NC::Buffer modified_item_prefix; NC::Buffer modified_item_prefix;
NC::Color color1;
NC::Color color2;
NC::Color empty_tags_color;
NC::Color header_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_color;
NC::Color main_highlight_color;
NC::Color progressbar_color;
NC::Color progressbar_elapsed_color;
NC::Color statusbar_color; NC::Color statusbar_color;
NC::Color alternative_ui_separator_color; NC::Color main_highlight_color;
NC::Color active_column_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; VisualizerType visualizer_type;
NC::Border window_border; NC::Border window_border;
@@ -166,7 +168,6 @@ struct Configuration
bool generate_win32_compatible_filenames; bool generate_win32_compatible_filenames;
bool ask_for_locked_screen_width_part; bool ask_for_locked_screen_width_part;
bool allow_for_physical_item_deletion; bool allow_for_physical_item_deletion;
bool progressbar_boldness;
bool startup_slave_screen_focus; bool startup_slave_screen_focus;
unsigned mpd_connection_timeout; unsigned mpd_connection_timeout;

View File

@@ -687,7 +687,10 @@ void Status::Changes::elapsedTime(bool update_elapsed)
*wHeader << NC::XY(second_start, 1); *wHeader << NC::XY(second_start, 1);
writeCyclicBuffer(second, *wHeader, second_line_scroll_begin, COLS-ps.length()-8-2, L" ** "); 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(); flags();
} }
@@ -719,11 +722,14 @@ void Status::Changes::flags()
*wHeader << Config.state_line_color; *wHeader << Config.state_line_color;
mvwhline(wHeader->raw(), 1, 0, 0, COLS); mvwhline(wHeader->raw(), 1, 0, 0, COLS);
*wHeader << NC::FormattedColor::End(Config.state_line_color);
if (!switch_state.empty()) 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 << Config.state_flags_color
<< NC::Format::Bold << switch_state << NC::Format::NoBold << switch_state
<< NC::Color::End << NC::FormattedColor::End(Config.state_flags_color)
<< "]"; << "]";
break; break;
case Design::Alternative: case Design::Alternative:
@@ -735,12 +741,15 @@ void Status::Changes::flags()
switch_state += m_crossfade ? m_crossfade : '-'; switch_state += m_crossfade ? m_crossfade : '-';
switch_state += m_db_updating ? m_db_updating : '-'; switch_state += m_db_updating ? m_db_updating : '-';
switch_state += ']'; 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 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); mvwhline(wHeader->raw(), 2, 0, 0, COLS);
*wHeader << NC::Color::End << NC::Format::NoBold; *wHeader << NC::FormattedColor::End(Config.alternative_ui_separator_color);
} }
break; break;
} }
@@ -749,7 +758,8 @@ void Status::Changes::flags()
void Status::Changes::mixer() 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; return;
switch (Config.design) switch (Config.design)
@@ -768,9 +778,10 @@ void Status::Changes::mixer()
VolumeState += boost::lexical_cast<std::string>(m_volume); VolumeState += boost::lexical_cast<std::string>(m_volume);
VolumeState += "%"; VolumeState += "%";
} }
*wHeader << Config.volume_color; *wHeader << NC::XY(wHeader->getWidth()-VolumeState.length(), 0)
*wHeader << NC::XY(wHeader->getWidth()-VolumeState.length(), 0) << VolumeState; << Config.volume_color
*wHeader << NC::Color::End; << VolumeState
<< NC::FormattedColor::End(Config.volume_color);
wHeader->refresh(); wHeader->refresh();
} }

View File

@@ -59,8 +59,6 @@ void Progressbar::draw(unsigned int elapsed, unsigned int time)
{ {
unsigned pb_width = wFooter->getWidth(); unsigned pb_width = wFooter->getWidth();
unsigned howlong = time ? pb_width*elapsed/time : 0; unsigned howlong = time ? pb_width*elapsed/time : 0;
if (Config.progressbar_boldness)
*wFooter << NC::Format::Bold;
*wFooter << Config.progressbar_color; *wFooter << Config.progressbar_color;
if (Config.progressbar[2] != '\0') if (Config.progressbar[2] != '\0')
{ {
@@ -71,6 +69,7 @@ void Progressbar::draw(unsigned int elapsed, unsigned int time)
} }
else else
mvwhline(wFooter->raw(), 0, 0, 0, pb_width); mvwhline(wFooter->raw(), 0, 0, 0, pb_width);
*wFooter << NC::FormattedColor::End(Config.progressbar_color);
if (time) if (time)
{ {
*wFooter << Config.progressbar_elapsed_color; *wFooter << Config.progressbar_elapsed_color;
@@ -79,11 +78,8 @@ void Progressbar::draw(unsigned int elapsed, unsigned int time)
*wFooter << Config.progressbar[0]; *wFooter << Config.progressbar[0];
if (howlong < wFooter->getWidth()) if (howlong < wFooter->getWidth())
*wFooter << Config.progressbar[1]; *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 Statusbar::ScopedLock::ScopedLock() noexcept

View File

@@ -43,20 +43,28 @@ void drawHeader()
switch (Config.design) switch (Config.design)
{ {
case Design::Classic: case Design::Classic:
*wHeader << NC::XY(0, 0) << NC::TermManip::ClearToEOL << NC::Format::Bold << myScreen->title() << NC::Format::NoBold; *wHeader << NC::XY(0, 0)
*wHeader << Config.volume_color; << NC::TermManip::ClearToEOL
*wHeader << NC::XY(wHeader->getWidth()-VolumeState.length(), 0) << VolumeState; << NC::Format::Bold
*wHeader << NC::Color::End; << myScreen->title()
<< NC::Format::NoBold
<< NC::XY(wHeader->getWidth()-VolumeState.length(), 0)
<< Config.volume_color
<< VolumeState
<< NC::FormattedColor::End(Config.volume_color);
break; break;
case Design::Alternative: case Design::Alternative:
std::wstring title = myScreen->title(); std::wstring title = myScreen->title();
*wHeader << NC::XY(0, 3) << NC::TermManip::ClearToEOL; *wHeader << NC::XY(0, 3)
*wHeader << NC::Format::Bold << Config.alternative_ui_separator_color; << NC::TermManip::ClearToEOL
<< Config.alternative_ui_separator_color;
mvwhline(wHeader->raw(), 2, 0, 0, COLS); mvwhline(wHeader->raw(), 2, 0, 0, COLS);
mvwhline(wHeader->raw(), 4, 0, 0, COLS); mvwhline(wHeader->raw(), 4, 0, 0, COLS);
*wHeader << NC::XY((COLS-wideLength(title))/2, 3); *wHeader << NC::FormattedColor::End(Config.alternative_ui_separator_color)
*wHeader << Config.header_color << title << NC::Color::End; << NC::XY((COLS-wideLength(title))/2, 3)
*wHeader << NC::Color::End << NC::Format::NoBold; << NC::Format::Bold
<< title
<< NC::Format::NoBold;
break; break;
} }
wHeader->refresh(); wHeader->refresh();

View File

@@ -18,9 +18,23 @@
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. * * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/ ***************************************************************************/
#include <boost/lexical_cast.hpp>
#include <cassert> #include <cassert>
#include "utility/type_conversions.h" #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) NC::Color charToColor(char c)
{ {
switch (c) switch (c)

View File

@@ -26,6 +26,8 @@
#include "mutable_song.h" #include "mutable_song.h"
#include "enums.h" #include "enums.h"
std::string channelsToString(int channels);
NC::Color charToColor(char c); NC::Color charToColor(char c);
std::string tagTypeToString(mpd_tag_type tag); std::string tagTypeToString(mpd_tag_type tag);