mirror of https://github.com/polybar/polybar.git
Compare commits
8 Commits
0a23199911
...
751ac7a5cc
Author | SHA1 | Date |
---|---|---|
dvermd | 751ac7a5cc | |
Roddy Rappaport | 11b522c313 | |
Roddy Rappaport | 82a81ce07c | |
Roddy Rappaport | c2dd279bf7 | |
patrick96 | 174ce34285 | |
dvermd | b5070bbc32 | |
dvermd | c9bba89d52 | |
dvermd | 9ff6d0cb10 |
|
@ -9,6 +9,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- An option `unmute-on-scroll` for `internal/pulseaudio` and `internal/alsa` to unmute audio when the user scrolls on the widget.
|
||||
|
||||
## [3.7.1] - 2023-11-27
|
||||
### Build
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
modules = {
|
||||
i3_test = {
|
||||
type = "internal/i3",
|
||||
-- this syntax is needed for key containing '-' or reserved word
|
||||
[ "wrapping-scroll" ] = true,
|
||||
format = "<label-state> <label-mode>"
|
||||
},
|
||||
mydate = {
|
||||
type = "internal/date",
|
||||
internal = "5",
|
||||
date = " %Y-%m-%d",
|
||||
time = "%H:%M",
|
||||
["time-alt"] = "%H:%M:%S",
|
||||
["format-underline"] = "#0a6cf5",
|
||||
label = "%date% %time%"
|
||||
},
|
||||
fs1 = {
|
||||
type = "internal/fs",
|
||||
interval = "25",
|
||||
mount = {"/"},
|
||||
["label-mounted"] = "%{F#0a81f5}%mountpoint%%{F-}: %percentage_used%%",
|
||||
["label-unmounted"] = "%mountpoint% not mounted",
|
||||
["label-unmounted-foreground"] = "#555555"
|
||||
},
|
||||
fs2 = {
|
||||
type = "internal/fs",
|
||||
interval = 25,
|
||||
mount = {"/home"},
|
||||
["label-mounted"] = "%{F#0a81f5}%mountpoint%%{F-}: %percentage_used%%",
|
||||
["label-unmounted"] = "%mountpoint% not mounted",
|
||||
["label-unmounted-foreground"] = "#555555"
|
||||
}
|
||||
}
|
||||
|
||||
bars = {
|
||||
bar_test = {
|
||||
monitor = "eDP-1",
|
||||
width = "100%",
|
||||
height = "18",
|
||||
radius = 4.0,
|
||||
["fixed-center"] = false,
|
||||
-- background = {"#222222", "#444444"},
|
||||
background = "#222222",
|
||||
foreground = "#dfdfdf",
|
||||
font = {"fixed:pixelsize=10;1"},
|
||||
["enable-ipc"] = true,
|
||||
["modules-center"] = "i3_test mydate fs1 fs2"
|
||||
}
|
||||
}
|
||||
|
|
@ -4,4 +4,4 @@
|
|||
sphinx~=7.2.6
|
||||
sphinx-rtd-theme~=2.0.0rc2
|
||||
sphinx-notfound-page~=1.0.0
|
||||
readthedocs-sphinx-search~=0.3.1
|
||||
readthedocs-sphinx-search~=0.3.2
|
||||
|
|
|
@ -153,6 +153,9 @@ internal/alsa
|
|||
``interval`` is the config setting in the module. Volume changed like this
|
||||
will never go above 100%.
|
||||
|
||||
if ``unmute-on-scroll`` is turned on, the sound will also be unmuted when
|
||||
this action is called.
|
||||
|
||||
:``toggle``:
|
||||
Toggles between muted and unmuted.
|
||||
|
||||
|
@ -165,6 +168,9 @@ internal/pulseaudio
|
|||
will never go above ~153% (if ``use-ui-max`` is set to ``true``) or 100% (if
|
||||
not).
|
||||
|
||||
if ``unmute-on-scroll`` is turned on, the sound will also be unmuted when
|
||||
this action is called.
|
||||
|
||||
:``toggle``:
|
||||
Toggles between muted and unmuted.
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <set>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "components/config.hpp"
|
||||
#include "components/eventloop.hpp"
|
||||
#include "components/types.hpp"
|
||||
#include "errors.hpp"
|
||||
|
|
|
@ -3,64 +3,80 @@
|
|||
#include <unordered_map>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "components/config_base.hpp"
|
||||
#include "components/config_ini.hpp"
|
||||
#include "components/config_lua.hpp"
|
||||
#include "components/logger.hpp"
|
||||
#include "errors.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "utils/env.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#if WITH_XRM
|
||||
#include "x11/xresources.hpp"
|
||||
#endif
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
DEFINE_ERROR(value_error);
|
||||
DEFINE_ERROR(key_error);
|
||||
|
||||
using valuemap_t = std::unordered_map<string, string>;
|
||||
using sectionmap_t = std::map<string, valuemap_t>;
|
||||
using file_list = vector<string>;
|
||||
|
||||
class config {
|
||||
public:
|
||||
explicit config(const logger& logger, string&& path, string&& bar)
|
||||
: m_log(logger), m_file(move(path)), m_barname(move(bar)){};
|
||||
explicit config(const logger& logger, const string& path)
|
||||
: m_log(logger), m_file(path){};
|
||||
|
||||
const string& filepath() const;
|
||||
string section() const;
|
||||
shared_ptr<config_ini> make_ini(const std::string& barname) {
|
||||
m_barname = barname;
|
||||
m_config_ini = make_shared<config_ini>(m_log, m_file, m_barname);
|
||||
return m_config_ini;
|
||||
}
|
||||
|
||||
static constexpr const char* BAR_PREFIX = "bar/";
|
||||
shared_ptr<config_lua> make_lua(const std::string& barname) {
|
||||
m_barname = barname;
|
||||
m_config_lua = make_shared<config_lua>(m_log, m_file, m_barname);
|
||||
return m_config_lua;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Instruct the config to connect to the xresource manager
|
||||
*/
|
||||
void use_xrm();
|
||||
const string& filepath() const {
|
||||
return m_file;
|
||||
}
|
||||
string section() const {
|
||||
if (m_config_ini) {
|
||||
return m_config_ini->section();
|
||||
} else {
|
||||
return m_config_lua->section();
|
||||
}
|
||||
}
|
||||
|
||||
void set_sections(sectionmap_t sections);
|
||||
file_list get_included_files() const {
|
||||
if (m_config_ini) {
|
||||
return m_config_ini->get_included_files();
|
||||
} else {
|
||||
return m_config_lua->get_included_files();
|
||||
}
|
||||
}
|
||||
|
||||
void set_included(file_list included);
|
||||
|
||||
file_list get_included_files() const;
|
||||
|
||||
void warn_deprecated(const string& section, const string& key, string replacement = "") const;
|
||||
void warn_deprecated(const string& section, const string& key, string replacement="") const {
|
||||
if (m_config_ini) {
|
||||
return m_config_ini->warn_deprecated(section, key, replacement);
|
||||
} else {
|
||||
return m_config_lua->warn_deprecated(section, key, replacement);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a given parameter exists
|
||||
*/
|
||||
bool has(const string& section, const string& key) const;
|
||||
|
||||
/**
|
||||
* Set parameter value
|
||||
*/
|
||||
void set(const string& section, const string& key, string&& value);
|
||||
bool has(const string& section, const string& key) const {
|
||||
if (m_config_ini) {
|
||||
return m_config_ini->has(section, key);
|
||||
} else {
|
||||
return m_config_lua->has(section, key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parameter for the current bar by name
|
||||
*/
|
||||
template <typename T = string>
|
||||
T get(const string& key) const {
|
||||
return get<T>(section(), key);
|
||||
if (m_config_ini) {
|
||||
return m_config_ini->get<T>(key);
|
||||
} else {
|
||||
return m_config_lua->get<T>(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,14 +84,11 @@ class config {
|
|||
*/
|
||||
template <typename T = string>
|
||||
T get(const string& section, const string& key) const {
|
||||
auto it = m_sections.find(section);
|
||||
if (it == m_sections.end()) {
|
||||
throw key_error("Missing section \"" + section + "\"");
|
||||
if (m_config_ini) {
|
||||
return m_config_ini->get<T>(section, key);
|
||||
} else {
|
||||
return m_config_lua->get<T>(section, key);
|
||||
}
|
||||
if (it->second.find(key) == it->second.end()) {
|
||||
throw key_error("Missing parameter \"" + section + "." + key + "\"");
|
||||
}
|
||||
return convert<T>(dereference(section, key, it->second.at(key)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -84,14 +97,10 @@ class config {
|
|||
*/
|
||||
template <typename T = string>
|
||||
T get(const string& section, const string& key, const T& default_value) const {
|
||||
try {
|
||||
string string_value{get<string>(section, key)};
|
||||
return convert<T>(dereference(move(section), move(key), move(string_value)));
|
||||
} catch (const key_error& err) {
|
||||
return default_value;
|
||||
} catch (const std::exception& err) {
|
||||
m_log.err("Invalid value for \"%s.%s\", using default value (reason: %s)", section, key, err.what());
|
||||
return default_value;
|
||||
if (m_config_ini) {
|
||||
return m_config_ini->get<T>(section, key, default_value);
|
||||
} else {
|
||||
return m_config_lua->get<T>(section, key, default_value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,22 +112,11 @@ class config {
|
|||
*/
|
||||
template <typename T = string>
|
||||
vector<pair<string, T>> get_with_prefix(const string& section, const string& key_prefix) const {
|
||||
auto it = m_sections.find(section);
|
||||
if (it == m_sections.end()) {
|
||||
throw key_error("Missing section \"" + section + "\"");
|
||||
if (m_config_ini) {
|
||||
return m_config_ini->get_with_prefix<T>(section, key_prefix);
|
||||
} else {
|
||||
return m_config_lua->get_with_prefix<T>(section, key_prefix);
|
||||
}
|
||||
|
||||
vector<pair<string, T>> list;
|
||||
for (const auto& kv_pair : it->second) {
|
||||
const auto& key = kv_pair.first;
|
||||
|
||||
if (key.substr(0, key_prefix.size()) == key_prefix) {
|
||||
const T& val = get<T>(section, key);
|
||||
list.emplace_back(key.substr(key_prefix.size()), val);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,7 +124,11 @@ class config {
|
|||
*/
|
||||
template <typename T = string>
|
||||
vector<T> get_list(const string& key) const {
|
||||
return get_list<T>(section(), key);
|
||||
if (m_config_ini) {
|
||||
return m_config_ini->get_list<T>(key);
|
||||
} else {
|
||||
return m_config_lua->get_list<T>(key);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,27 +136,11 @@ class config {
|
|||
*/
|
||||
template <typename T = string>
|
||||
vector<T> get_list(const string& section, const string& key) const {
|
||||
vector<T> results;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
string string_value{get<string>(section, key + "-" + to_string(results.size()))};
|
||||
|
||||
if (!string_value.empty()) {
|
||||
results.emplace_back(convert<T>(dereference(section, key, move(string_value))));
|
||||
} else {
|
||||
results.emplace_back(convert<T>(move(string_value)));
|
||||
}
|
||||
} catch (const key_error& err) {
|
||||
break;
|
||||
}
|
||||
if (m_config_ini) {
|
||||
return m_config_ini->get_list<T>(section, key);
|
||||
} else {
|
||||
return m_config_lua->get_list<T>(section, key);
|
||||
}
|
||||
|
||||
if (results.empty()) {
|
||||
throw key_error("Missing parameter \"" + section + "." + key + "-0\"");
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -163,31 +149,11 @@ class config {
|
|||
*/
|
||||
template <typename T = string>
|
||||
vector<T> get_list(const string& section, const string& key, const vector<T>& default_value) const {
|
||||
vector<T> results;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
string string_value{get<string>(section, key + "-" + to_string(results.size()))};
|
||||
|
||||
if (!string_value.empty()) {
|
||||
results.emplace_back(convert<T>(dereference(section, key, move(string_value))));
|
||||
} else {
|
||||
results.emplace_back(convert<T>(move(string_value)));
|
||||
}
|
||||
} catch (const key_error& err) {
|
||||
break;
|
||||
} catch (const std::exception& err) {
|
||||
m_log.err("Invalid value in list \"%s.%s\", using list as-is (reason: %s)", section, key, err.what());
|
||||
return default_value;
|
||||
}
|
||||
if (m_config_ini) {
|
||||
return m_config_ini->get_list<T>(section, key, default_value);
|
||||
} else {
|
||||
return m_config_lua->get_list<T>(section, key, default_value);
|
||||
}
|
||||
|
||||
if (!results.empty()) {
|
||||
return results;
|
||||
;
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -197,76 +163,20 @@ class config {
|
|||
*/
|
||||
template <typename T = string>
|
||||
T deprecated(const string& section, const string& old, const string& newkey, const T& fallback) const {
|
||||
try {
|
||||
T value{get<T>(section, old)};
|
||||
warn_deprecated(section, old, newkey);
|
||||
return value;
|
||||
} catch (const key_error& err) {
|
||||
return get<T>(section, newkey, fallback);
|
||||
} catch (const std::exception& err) {
|
||||
m_log.err("Invalid value for \"%s.%s\", using fallback key \"%s.%s\" (reason: %s)", section, old, section, newkey,
|
||||
err.what());
|
||||
return get<T>(section, newkey, fallback);
|
||||
if (m_config_ini) {
|
||||
return m_config_ini->deprecated<T>(section, old, newkey, fallback);
|
||||
} else {
|
||||
return m_config_lua->deprecated<T>(section, old, newkey, fallback);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void copy_inherited();
|
||||
|
||||
template <typename T>
|
||||
T convert(string&& value) const;
|
||||
|
||||
/**
|
||||
* Dereference value reference
|
||||
*/
|
||||
string dereference(const string& section, const string& key, const string& var) const;
|
||||
|
||||
/**
|
||||
* Dereference local value reference defined using:
|
||||
* ${root.key}
|
||||
* ${root.key:fallback}
|
||||
* ${self.key}
|
||||
* ${self.key:fallback}
|
||||
* ${section.key}
|
||||
* ${section.key:fallback}
|
||||
*/
|
||||
string dereference_local(string section, const string& key, const string& current_section) const;
|
||||
|
||||
/**
|
||||
* Dereference environment variable reference defined using:
|
||||
* ${env:key}
|
||||
* ${env:key:fallback value}
|
||||
*/
|
||||
string dereference_env(string var) const;
|
||||
|
||||
/**
|
||||
* Dereference X resource db value defined using:
|
||||
* ${xrdb:key}
|
||||
* ${xrdb:key:fallback value}
|
||||
*/
|
||||
string dereference_xrdb(string var) const;
|
||||
|
||||
/**
|
||||
* Dereference file reference by reading its contents
|
||||
* ${file:/absolute/file/path}
|
||||
* ${file:/absolute/file/path:fallback value}
|
||||
*/
|
||||
string dereference_file(string var) const;
|
||||
|
||||
private:
|
||||
const logger& m_log;
|
||||
string m_file;
|
||||
string m_barname;
|
||||
sectionmap_t m_sections{};
|
||||
|
||||
/**
|
||||
* Absolute path of all files that were parsed in the process of parsing the
|
||||
* config (Path of the main config file also included)
|
||||
*/
|
||||
file_list m_included;
|
||||
#if WITH_XRM
|
||||
unique_ptr<xresource_manager> m_xrm;
|
||||
#endif
|
||||
shared_ptr<config_ini> m_config_ini;
|
||||
shared_ptr<config_lua> m_config_lua;
|
||||
};
|
||||
|
||||
POLYBAR_NS_END
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "errors.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
DEFINE_ERROR(value_error);
|
||||
DEFINE_ERROR(key_error);
|
||||
|
||||
using valuemap_t = std::unordered_map<string, string>;
|
||||
using sectionmap_t = std::map<string, valuemap_t>;
|
||||
using file_list = vector<string>;
|
||||
|
||||
namespace config_utils {
|
||||
template <typename T>
|
||||
T convert(string&& value);
|
||||
};
|
||||
|
||||
POLYBAR_NS_END
|
|
@ -0,0 +1,263 @@
|
|||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "components/config_base.hpp"
|
||||
#include "components/logger.hpp"
|
||||
#include "errors.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "utils/env.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#if WITH_XRM
|
||||
#include "x11/xresources.hpp"
|
||||
#endif
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
class config_ini {
|
||||
public:
|
||||
explicit config_ini(const logger& logger, const string& path, const string& bar)
|
||||
: m_log(logger), m_file(path), m_barname(bar){};
|
||||
|
||||
const string& filepath() const;
|
||||
string section() const;
|
||||
|
||||
static constexpr const char* BAR_PREFIX = "bar/";
|
||||
|
||||
/**
|
||||
* @brief Instruct the config to connect to the xresource manager
|
||||
*/
|
||||
void use_xrm();
|
||||
|
||||
void set_sections(sectionmap_t sections);
|
||||
|
||||
void set_included(file_list included);
|
||||
|
||||
file_list get_included_files() const;
|
||||
|
||||
void warn_deprecated(const string& section, const string& key, string replacement = "") const;
|
||||
|
||||
/**
|
||||
* Returns true if a given parameter exists
|
||||
*/
|
||||
bool has(const string& section, const string& key) const;
|
||||
|
||||
/**
|
||||
* Set parameter value
|
||||
*/
|
||||
void set(const string& section, const string& key, string&& value);
|
||||
|
||||
/**
|
||||
* Get parameter for the current bar by name
|
||||
*/
|
||||
template <typename T = string>
|
||||
T get(const string& key) const {
|
||||
return get<T>(section(), key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value of a variable by section and parameter name
|
||||
*/
|
||||
template <typename T = string>
|
||||
T get(const string& section, const string& key) const {
|
||||
auto it = m_sections.find(section);
|
||||
if (it == m_sections.end()) {
|
||||
throw key_error("Missing section \"" + section + "\"");
|
||||
}
|
||||
if (it->second.find(key) == it->second.end()) {
|
||||
throw key_error("Missing parameter \"" + section + "." + key + "\"");
|
||||
}
|
||||
return config_utils::convert<T>(dereference(section, key, it->second.at(key)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value of a variable by section and parameter name
|
||||
* with a default value in case the parameter isn't defined
|
||||
*/
|
||||
template <typename T = string>
|
||||
T get(const string& section, const string& key, const T& default_value) const {
|
||||
try {
|
||||
string string_value{get<string>(section, key)};
|
||||
return config_utils::convert<T>(dereference(move(section), move(key), move(string_value)));
|
||||
} catch (const key_error& err) {
|
||||
return default_value;
|
||||
} catch (const std::exception& err) {
|
||||
m_log.err("Invalid value for \"%s.%s\", using default value (reason: %s)", section, key, err.what());
|
||||
return default_value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of key-value pairs starting with a prefix by section.
|
||||
*
|
||||
* Eg: if you have in config `env-FOO = bar`,
|
||||
* get_with_prefix(section, "env-") will return [{"FOO", "bar"}]
|
||||
*/
|
||||
template <typename T = string>
|
||||
vector<pair<string, T>> get_with_prefix(const string& section, const string& key_prefix) const {
|
||||
auto it = m_sections.find(section);
|
||||
if (it == m_sections.end()) {
|
||||
throw key_error("Missing section \"" + section + "\"");
|
||||
}
|
||||
|
||||
vector<pair<string, T>> list;
|
||||
for (const auto& kv_pair : it->second) {
|
||||
const auto& key = kv_pair.first;
|
||||
|
||||
if (key.substr(0, key_prefix.size()) == key_prefix) {
|
||||
const T& val = get<T>(section, key);
|
||||
list.emplace_back(key.substr(key_prefix.size()), val);
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of values for the current bar by name
|
||||
*/
|
||||
template <typename T = string>
|
||||
vector<T> get_list(const string& key) const {
|
||||
return get_list<T>(section(), key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of values by section and parameter name
|
||||
*/
|
||||
template <typename T = string>
|
||||
vector<T> get_list(const string& section, const string& key) const {
|
||||
vector<T> results;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
string string_value{get<string>(section, key + "-" + to_string(results.size()))};
|
||||
|
||||
if (!string_value.empty()) {
|
||||
results.emplace_back( config_utils::convert<T>(dereference(section, key, move(string_value))));
|
||||
} else {
|
||||
results.emplace_back( config_utils::convert<T>(move(string_value)));
|
||||
}
|
||||
} catch (const key_error& err) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (results.empty()) {
|
||||
throw key_error("Missing parameter \"" + section + "." + key + "-0\"");
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of values by section and parameter name
|
||||
* with a default list in case the list isn't defined
|
||||
*/
|
||||
template <typename T = string>
|
||||
vector<T> get_list(const string& section, const string& key, const vector<T>& default_value) const {
|
||||
vector<T> results;
|
||||
|
||||
while (true) {
|
||||
try {
|
||||
string string_value{get<string>(section, key + "-" + to_string(results.size()))};
|
||||
|
||||
if (!string_value.empty()) {
|
||||
results.emplace_back( config_utils::convert<T>(dereference(section, key, move(string_value))));
|
||||
} else {
|
||||
results.emplace_back( config_utils::convert<T>(move(string_value)));
|
||||
}
|
||||
} catch (const key_error& err) {
|
||||
break;
|
||||
} catch (const std::exception& err) {
|
||||
m_log.err("Invalid value in list \"%s.%s\", using list as-is (reason: %s)", section, key, err.what());
|
||||
return default_value;
|
||||
}
|
||||
}
|
||||
|
||||
if (!results.empty()) {
|
||||
return results;
|
||||
;
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to load value using the deprecated key name. If successful show a
|
||||
* warning message. If it fails load the value using the new key and given
|
||||
* fallback value
|
||||
*/
|
||||
template <typename T = string>
|
||||
T deprecated(const string& section, const string& old, const string& newkey, const T& fallback) const {
|
||||
try {
|
||||
T value{get<T>(section, old)};
|
||||
warn_deprecated(section, old, newkey);
|
||||
return value;
|
||||
} catch (const key_error& err) {
|
||||
return get<T>(section, newkey, fallback);
|
||||
} catch (const std::exception& err) {
|
||||
m_log.err("Invalid value for \"%s.%s\", using fallback key \"%s.%s\" (reason: %s)", section, old, section, newkey,
|
||||
err.what());
|
||||
return get<T>(section, newkey, fallback);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void copy_inherited();
|
||||
|
||||
/**
|
||||
* Dereference value reference
|
||||
*/
|
||||
string dereference(const string& section, const string& key, const string& var) const;
|
||||
|
||||
/**
|
||||
* Dereference local value reference defined using:
|
||||
* ${root.key}
|
||||
* ${root.key:fallback}
|
||||
* ${self.key}
|
||||
* ${self.key:fallback}
|
||||
* ${section.key}
|
||||
* ${section.key:fallback}
|
||||
*/
|
||||
string dereference_local(string section, const string& key, const string& current_section) const;
|
||||
|
||||
/**
|
||||
* Dereference environment variable reference defined using:
|
||||
* ${env:key}
|
||||
* ${env:key:fallback value}
|
||||
*/
|
||||
string dereference_env(string var) const;
|
||||
|
||||
/**
|
||||
* Dereference X resource db value defined using:
|
||||
* ${xrdb:key}
|
||||
* ${xrdb:key:fallback value}
|
||||
*/
|
||||
string dereference_xrdb(string var) const;
|
||||
|
||||
/**
|
||||
* Dereference file reference by reading its contents
|
||||
* ${file:/absolute/file/path}
|
||||
* ${file:/absolute/file/path:fallback value}
|
||||
*/
|
||||
string dereference_file(string var) const;
|
||||
|
||||
private:
|
||||
const logger& m_log;
|
||||
string m_file;
|
||||
string m_barname;
|
||||
sectionmap_t m_sections{};
|
||||
|
||||
/**
|
||||
* Absolute path of all files that were parsed in the process of parsing the
|
||||
* config (Path of the main config file also included)
|
||||
*/
|
||||
file_list m_included;
|
||||
#if WITH_XRM
|
||||
unique_ptr<xresource_manager> m_xrm;
|
||||
#endif
|
||||
};
|
||||
|
||||
POLYBAR_NS_END
|
|
@ -0,0 +1,294 @@
|
|||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
|
||||
#include "common.hpp"
|
||||
#include "components/config_base.hpp"
|
||||
#include "components/types.hpp"
|
||||
#include "components/logger.hpp"
|
||||
#include "errors.hpp"
|
||||
#include "settings.hpp"
|
||||
#include "utils/color.hpp"
|
||||
#include "utils/env.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
#include <sol/sol.hpp>
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
class config_lua {
|
||||
public:
|
||||
explicit config_lua(const logger& logger, const string& path, const string& bar)
|
||||
: m_log(logger), m_file(path), m_barname(bar){
|
||||
m_state.open_libraries();
|
||||
|
||||
m_state.script_file(path, [](lua_State*, sol::protected_function_result pfr) -> sol::protected_function_result {
|
||||
sol::error err = pfr;
|
||||
throw application_error(string("Error loading lua config: ") + err.what(), 0);
|
||||
});
|
||||
|
||||
if (m_barname.empty()) {
|
||||
sol::optional<sol::table> opt_bars = m_state[BARS_CONTAINER];
|
||||
if (opt_bars) {
|
||||
sol::table bars = *opt_bars;
|
||||
|
||||
vector<string> keys(bars.size());
|
||||
for (const pair<sol::object, sol::object> &kv_pair: bars) {
|
||||
sol::object k = kv_pair.first;
|
||||
if (k.is<string>()) {
|
||||
keys.push_back(k.as<string>());
|
||||
} else {
|
||||
throw application_error("The config file contains a bar with a non string name.");
|
||||
}
|
||||
}
|
||||
|
||||
if (keys.size() == 1) {
|
||||
m_barname = keys[0];
|
||||
} else if (bars.empty()){
|
||||
throw application_error("The config file contains no bar.");
|
||||
} else {
|
||||
throw application_error("The config file contains multiple bars, but no bar name was given. Available bars: " +
|
||||
string_util::join(keys, ", "));
|
||||
}
|
||||
} else {
|
||||
throw application_error("The config file contains no bar.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const string& filepath() const;
|
||||
string section() const;
|
||||
|
||||
static constexpr const char* BARS_CONTAINER = "bars";
|
||||
static constexpr const char* MODULES_CONTAINER = "modules";
|
||||
|
||||
file_list get_included_files() const;
|
||||
|
||||
void warn_deprecated(const string& section, const string& key, string replacement = "") const;
|
||||
|
||||
/**
|
||||
* Returns true if a given parameter exists
|
||||
*/
|
||||
bool has(const string& section, const string& key) const;
|
||||
|
||||
/**
|
||||
* Get parameter for the current bar by name
|
||||
*/
|
||||
template <typename T = string>
|
||||
T get(const string& key) const {
|
||||
return get<T>(section(), key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get value of a variable by section and parameter name
|
||||
*/
|
||||
template <typename T=string>
|
||||
T get(const string& section, const string& key) const {
|
||||
return config_utils::convert<T>(move(lua_get<string>(section, key)));
|
||||
}
|
||||
|
||||
template <typename T=string>
|
||||
T get(const string& section, const string& key, const T& default_value) const {
|
||||
try {
|
||||
return get<T>(section, key);
|
||||
} catch (const key_error& err) {
|
||||
return default_value;
|
||||
} catch (const std::exception& err) {
|
||||
pair<string, std::optional<string>> entries = get_entries(section);
|
||||
if (entries.second){
|
||||
m_log.err("Invalid value for \"%s[%s][%s]\", using default value (reason: %s)", entries.first, *entries.second, key, err.what());
|
||||
} else {
|
||||
m_log.err("Invalid value for \"%s[%s]\", using default value (reason: %s)", entries.first, key, err.what());
|
||||
}
|
||||
|
||||
return default_value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of key-value pairs starting with a prefix by section.
|
||||
*
|
||||
* Eg: if you have in config `env-FOO = bar`,
|
||||
* get_with_prefix(section, "env-") will return [{"FOO", "bar"}]
|
||||
*/
|
||||
template <typename T = string>
|
||||
vector<pair<string, T>> get_with_prefix(const string& section, const string& key_prefix) const {
|
||||
pair<sol::table, string> table_message = lua_get_table(section);
|
||||
sol::table table = table_message.first;
|
||||
vector<pair<string, T>> kv_vec;
|
||||
for (const pair<sol::object, sol::object> &kv_pair: table) {
|
||||
sol::object k = kv_pair.first;
|
||||
sol::object v = kv_pair.second;
|
||||
if (k.is<string>()) {
|
||||
string k_str = k.as<string>();
|
||||
if (k_str.substr(0, key_prefix.size()) == key_prefix) {
|
||||
if (v.is<T>()) {
|
||||
kv_vec.push_back({k_str, v.as<T>()});
|
||||
} else if (v.is<string>()) {
|
||||
kv_vec.push_back({k_str, config_utils::convert<T>(move(v.as<string>()))});
|
||||
} else {
|
||||
throw value_error("Wrong data type for \"" + table_message.second+ "[" + k_str + "]\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return kv_vec;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of values for the current bar by name
|
||||
*/
|
||||
template <typename T = string>
|
||||
vector<T> get_list(const string& key) const {
|
||||
return get_list<T>(section(), key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of values by section and parameter name
|
||||
*/
|
||||
template <typename T = string>
|
||||
vector<T> get_list(const string& section, const string& key) const {
|
||||
pair<sol::table, string> table_message = lua_get_table(section);
|
||||
sol::table table = table_message.first;
|
||||
string message_key = table_message.second;
|
||||
|
||||
if (!config_lua::has(table, key)) {
|
||||
throw key_error("Missing parameter \"" + message_key + "[" + key + "]\"");
|
||||
}
|
||||
sol::optional<vector<sol::optional<string>>> value = table[key];
|
||||
if (value == sol::nullopt) {
|
||||
sol::optional<string> value = table[key];
|
||||
if (value != sol::nullopt) {
|
||||
throw key_error("Not a list value for parameter \"" + message_key + "[" + key + "]\"");
|
||||
} else {
|
||||
throw value_error("Wrong type for parameter \"" + message_key + "[" + key + "]\"");
|
||||
}
|
||||
}
|
||||
vector<sol::optional<string>> vec = *value;
|
||||
vector<T> result{vec.size()};
|
||||
for (size_t i = 0; i < vec.size(); i++) {
|
||||
const sol::optional<string>& value = vec[i];
|
||||
if (value) {
|
||||
string value_str = *value;
|
||||
result.push_back(config_utils::convert<T>(move(value_str)));
|
||||
} else {
|
||||
throw value_error("The element of \"" + message_key + "\" at position " + to_string(i) + " cannot be converted to the expected type");
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list of values by section and parameter name
|
||||
* with a default list in case the list isn't defined
|
||||
*/
|
||||
template <typename T = string>
|
||||
vector<T> get_list(const string& section, const string& key, const vector<T>& default_value) const {
|
||||
try {
|
||||
vector<T> results = get_list<T>(section, key);
|
||||
if (!results.empty()) {
|
||||
return results;
|
||||
}
|
||||
return default_value;
|
||||
|
||||
} catch (const key_error&) {
|
||||
return default_value;
|
||||
} catch (const std::exception& err) {
|
||||
pair<string, std::optional<string>> entries = get_entries(section);
|
||||
if (entries.second){
|
||||
m_log.err("Invalid value for \"%s[%s][%s]\", using list as-is (reason: %s)", entries.first, *entries.second, key, err.what());
|
||||
} else {
|
||||
m_log.err("Invalid value for \"%s[%s]\", using list as-is (reason: %s)", entries.first, key, err.what());
|
||||
}
|
||||
return default_value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to load value using the deprecated key name. If successful show a
|
||||
* warning message. If it fails load the value using the new key and given
|
||||
* fallback value
|
||||
*/
|
||||
template <typename T = string>
|
||||
T deprecated(const string& section, const string& old, const string& newkey, const T& fallback) const {
|
||||
try {
|
||||
T value{get<T>(section, old)};
|
||||
warn_deprecated(section, old, newkey);
|
||||
return value;
|
||||
} catch (const key_error& err) {
|
||||
return get<T>(section, newkey, fallback);
|
||||
} catch (const std::exception& err) {
|
||||
// TODO improve message
|
||||
m_log.err("Invalid value for \"%s.%s\", using fallback key \"%s.%s\" (reason: %s)", section, old, section, newkey,
|
||||
err.what());
|
||||
pair<string, std::optional<string>> entries = get_entries(section);
|
||||
if (entries.second){
|
||||
m_log.err("Invalid value for \"%s[%s][%s]\", fallback key \"%s[%s][%s]\" (reason: %s)", entries.first, *entries.second, old, entries.first, *entries.second, newkey, err.what());
|
||||
} else {
|
||||
m_log.err("Invalid value for \"%s[%s]\", fallback key \"%s[%s]\" (reason: %s)", entries.first, old, entries.first, newkey, err.what());
|
||||
}
|
||||
return get<T>(section, newkey, fallback);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
pair<string, std::optional<string>> get_entries(const string& section) const;
|
||||
|
||||
/**
|
||||
* Returns true if a given parameter exists in the lua table
|
||||
*/
|
||||
static bool has(const sol::table& table, const string& key);
|
||||
|
||||
/**
|
||||
* Returns true if a given parameter exists in the lua table
|
||||
*/
|
||||
static bool has(const sol::state& table, const string& key);
|
||||
|
||||
pair<sol::table, string> lua_get_table(const string& section) const;
|
||||
|
||||
template <typename T=string>
|
||||
T lua_get(const string& section, const string& key) const {
|
||||
pair<string, std::optional<string>> entries = get_entries(section);
|
||||
|
||||
if (!config_lua::has(m_state, entries.first)) {
|
||||
throw key_error("Missing entry \"" + entries.first + "\"");
|
||||
}
|
||||
sol::optional<sol::table> opt_table = m_state[entries.first];
|
||||
if (opt_table == sol::nullopt) {
|
||||
throw key_error("Wrong type for entry \"" + entries.first + "\": expecting table");
|
||||
}
|
||||
string message_key = entries.first;
|
||||
sol::table table = *opt_table;
|
||||
if (entries.second) {
|
||||
message_key += "[" + *entries.second + "]";
|
||||
if (!config_lua::has(table, *entries.second)) {
|
||||
throw key_error("Missing entry \"" + message_key + "\"");
|
||||
}
|
||||
sol::optional<sol::table> opt_table = table[*entries.second];
|
||||
if (opt_table == sol::nullopt) {
|
||||
throw key_error("Wrong type for entry \"" + message_key + "\": expecting table");
|
||||
}
|
||||
table = *opt_table;
|
||||
}
|
||||
|
||||
if (!config_lua::has(table, key)) {
|
||||
throw key_error("Missing parameter \"" + message_key + "[" + key + "]\"");
|
||||
}
|
||||
sol::optional<T> value = table[key];
|
||||
if (value) {
|
||||
return *value;
|
||||
} else {
|
||||
throw value_error("Wrong type for parameter \"" + message_key + "[" + key + "]\"");
|
||||
}
|
||||
}
|
||||
|
||||
const logger& m_log;
|
||||
string m_file;
|
||||
string m_barname;
|
||||
sol::state m_state;
|
||||
};
|
||||
|
||||
POLYBAR_NS_END
|
|
@ -215,6 +215,8 @@ class config_parser {
|
|||
*/
|
||||
bool is_valid_name(const string& name);
|
||||
|
||||
bool is_lua_file() const;
|
||||
|
||||
vector<string> get_bars(const sectionmap_t& sections) const;
|
||||
|
||||
/**
|
||||
|
|
|
@ -67,6 +67,7 @@ namespace modules {
|
|||
map<control, control_t> m_ctrl;
|
||||
int m_headphoneid{0};
|
||||
bool m_mapped{false};
|
||||
bool m_unmute_on_scroll{false};
|
||||
int m_interval{5};
|
||||
atomic<bool> m_muted{false};
|
||||
atomic<bool> m_headphones{false};
|
||||
|
|
|
@ -51,6 +51,7 @@ namespace modules {
|
|||
pulseaudio_t m_pulseaudio;
|
||||
|
||||
int m_interval{5};
|
||||
bool m_unmute_on_scroll{false};
|
||||
atomic<bool> m_muted{false};
|
||||
atomic<int> m_volume{0};
|
||||
atomic<double> m_decibels{0};
|
||||
|
|
|
@ -36,3 +36,13 @@ if(ENABLE_I3)
|
|||
endif()
|
||||
|
||||
# }}}
|
||||
# Library: sol2 {{{
|
||||
|
||||
# if(ENABLE_LUA)
|
||||
add_library(sol2 INTERFACE)
|
||||
target_include_directories(sol2 INTERFACE ${PROJECT_SOURCE_DIR}/lib/sol2)
|
||||
target_link_libraries(sol2 INTERFACE lua)
|
||||
target_compile_definitions(sol2 INTERFACE SOL_ALL_SAFETIES_ON=1)
|
||||
# endif()
|
||||
|
||||
# }}}
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013-2022 Rapptz, ThePhD, and contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,53 @@
|
|||
// The MIT License (MIT)
|
||||
|
||||
// Copyright (c) 2013-2020 Rapptz, ThePhD and contributors
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
// this software and associated documentation files (the "Software"), to deal in
|
||||
// the Software without restriction, including without limitation the rights to
|
||||
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
// the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
// subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// This file was generated with a script.
|
||||
// Generated 2022-06-25 08:14:19.336233 UTC
|
||||
// This header was generated with sol v3.3.0 (revision eba86625)
|
||||
// https://github.com/ThePhD/sol2
|
||||
|
||||
#ifndef SOL_SINGLE_CONFIG_HPP
|
||||
#define SOL_SINGLE_CONFIG_HPP
|
||||
|
||||
// beginning of sol/config.hpp
|
||||
|
||||
/* Base, empty configuration file!
|
||||
|
||||
To override, place a file in your include paths of the form:
|
||||
|
||||
. (your include path here)
|
||||
| sol (directory, or equivalent)
|
||||
| config.hpp (your config.hpp file)
|
||||
|
||||
So that when sol2 includes the file
|
||||
|
||||
#include <sol/config.hpp>
|
||||
|
||||
it gives you the configuration values you desire. Configuration values can be
|
||||
seen in the safety.rst of the doc/src, or at
|
||||
https://sol2.readthedocs.io/en/latest/safety.html ! You can also pass them through
|
||||
the build system, or the command line options of your compiler.
|
||||
|
||||
*/
|
||||
|
||||
// end of sol/config.hpp
|
||||
|
||||
#endif // SOL_SINGLE_CONFIG_HPP
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -60,7 +60,9 @@ set(POLY_SOURCES
|
|||
${src_dir}/components/bar.cpp
|
||||
${src_dir}/components/builder.cpp
|
||||
${src_dir}/components/command_line.cpp
|
||||
${src_dir}/components/config.cpp
|
||||
${src_dir}/components/config_base.cpp
|
||||
${src_dir}/components/config_ini.cpp
|
||||
${src_dir}/components/config_lua.cpp
|
||||
${src_dir}/components/config_parser.cpp
|
||||
${src_dir}/components/controller.cpp
|
||||
${src_dir}/components/logger.cpp
|
||||
|
@ -161,6 +163,7 @@ target_link_libraries(poly PUBLIC
|
|||
Cairo::CairoFC
|
||||
xpp
|
||||
LibUV::LibUV
|
||||
sol2
|
||||
)
|
||||
|
||||
if (TARGET i3ipc++)
|
||||
|
|
|
@ -0,0 +1,165 @@
|
|||
#include "components/config_base.hpp"
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include "cairo/utils.hpp"
|
||||
#include "components/types.hpp"
|
||||
#include "utils/color.hpp"
|
||||
#include "utils/factory.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/units.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
namespace chrono = std::chrono;
|
||||
namespace config_utils {
|
||||
|
||||
template <>
|
||||
string convert(string&& value) {
|
||||
return forward<string>(value);
|
||||
}
|
||||
|
||||
template <>
|
||||
const char* convert(string&& value) {
|
||||
return value.c_str();
|
||||
}
|
||||
|
||||
template <>
|
||||
char convert(string&& value) {
|
||||
return value.c_str()[0];
|
||||
}
|
||||
|
||||
template <>
|
||||
int convert(string&& value) {
|
||||
return std::strtol(value.c_str(), nullptr, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
short convert(string&& value) {
|
||||
return static_cast<short>(std::strtol(value.c_str(), nullptr, 10));
|
||||
}
|
||||
|
||||
template <>
|
||||
bool convert(string&& value) {
|
||||
string lower{string_util::lower(forward<string>(value))};
|
||||
|
||||
return (lower == "true" || lower == "yes" || lower == "on" || lower == "1");
|
||||
}
|
||||
|
||||
template <>
|
||||
float convert(string&& value) {
|
||||
return std::strtof(value.c_str(), nullptr);
|
||||
}
|
||||
|
||||
template <>
|
||||
double convert(string&& value) {
|
||||
return std::strtod(value.c_str(), nullptr);
|
||||
}
|
||||
|
||||
template <>
|
||||
long convert(string&& value) {
|
||||
return std::strtol(value.c_str(), nullptr, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
long long convert(string&& value) {
|
||||
return std::strtoll(value.c_str(), nullptr, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned char convert(string&& value) {
|
||||
return std::strtoul(value.c_str(), nullptr, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned short convert(string&& value) {
|
||||
return std::strtoul(value.c_str(), nullptr, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned int convert(string&& value) {
|
||||
return std::strtoul(value.c_str(), nullptr, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned long convert(string&& value) {
|
||||
unsigned long v{std::strtoul(value.c_str(), nullptr, 10)};
|
||||
return v < ULONG_MAX ? v : 0UL;
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned long long convert(string&& value) {
|
||||
unsigned long long v{std::strtoull(value.c_str(), nullptr, 10)};
|
||||
return v < ULLONG_MAX ? v : 0ULL;
|
||||
}
|
||||
|
||||
template <>
|
||||
spacing_val convert(string&& value) {
|
||||
return units_utils::parse_spacing(value);
|
||||
}
|
||||
|
||||
template <>
|
||||
extent_val convert(std::string&& value) {
|
||||
return units_utils::parse_extent(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows a new format for pixel sizes (like width in the bar section)
|
||||
*
|
||||
* The new format is X%:Z, where X is in [0, 100], and Z is any real value
|
||||
* describing a pixel offset. The actual value is calculated by X% * max + Z
|
||||
*/
|
||||
template <>
|
||||
percentage_with_offset convert(string&& value) {
|
||||
size_t i = value.find(':');
|
||||
|
||||
if (i == std::string::npos) {
|
||||
if (value.find('%') != std::string::npos) {
|
||||
return {std::stod(value), {}};
|
||||
} else {
|
||||
return {0., convert<extent_val>(move(value))};
|
||||
}
|
||||
} else {
|
||||
std::string percentage = value.substr(0, i - 1);
|
||||
return {std::stod(percentage), convert<extent_val>(value.substr(i + 1))};
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
chrono::seconds convert(string&& value) {
|
||||
return chrono::seconds{convert<chrono::seconds::rep>(forward<string>(value))};
|
||||
}
|
||||
|
||||
template <>
|
||||
chrono::milliseconds convert(string&& value) {
|
||||
return chrono::milliseconds{convert<chrono::milliseconds::rep>(forward<string>(value))};
|
||||
}
|
||||
|
||||
template <>
|
||||
chrono::duration<double> convert(string&& value) {
|
||||
return chrono::duration<double>{convert<double>(forward<string>(value))};
|
||||
}
|
||||
|
||||
template <>
|
||||
rgba convert(string&& value) {
|
||||
if (value.empty()) {
|
||||
return rgba{};
|
||||
}
|
||||
|
||||
rgba ret{value};
|
||||
|
||||
if (!ret.has_color()) {
|
||||
throw value_error("\"" + value + "\" is an invalid color value.");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
cairo_operator_t convert(string&& value) {
|
||||
return cairo::utils::str2operator(forward<string>(value), CAIRO_OPERATOR_OVER);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
POLYBAR_NS_END
|
|
@ -1,16 +1,4 @@
|
|||
#include "components/config.hpp"
|
||||
|
||||
#include <climits>
|
||||
#include <cmath>
|
||||
#include <fstream>
|
||||
|
||||
#include "cairo/utils.hpp"
|
||||
#include "components/types.hpp"
|
||||
#include "utils/color.hpp"
|
||||
#include "utils/env.hpp"
|
||||
#include "utils/factory.hpp"
|
||||
#include "utils/string.hpp"
|
||||
#include "utils/units.hpp"
|
||||
#include "components/config_ini.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
|
@ -19,18 +7,18 @@ namespace chrono = std::chrono;
|
|||
/**
|
||||
* Get path of loaded file
|
||||
*/
|
||||
const string& config::filepath() const {
|
||||
const string& config_ini::filepath() const {
|
||||
return m_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the section name of the bar in use
|
||||
*/
|
||||
string config::section() const {
|
||||
string config_ini::section() const {
|
||||
return BAR_PREFIX + m_barname;
|
||||
}
|
||||
|
||||
void config::use_xrm() {
|
||||
void config_ini::use_xrm() {
|
||||
#if WITH_XRM
|
||||
/*
|
||||
* Initialize the xresource manager if there are any xrdb refs
|
||||
|
@ -43,23 +31,23 @@ void config::use_xrm() {
|
|||
#endif
|
||||
}
|
||||
|
||||
void config::set_sections(sectionmap_t sections) {
|
||||
void config_ini::set_sections(sectionmap_t sections) {
|
||||
m_sections = move(sections);
|
||||
copy_inherited();
|
||||
}
|
||||
|
||||
void config::set_included(file_list included) {
|
||||
void config_ini::set_included(file_list included) {
|
||||
m_included = move(included);
|
||||
}
|
||||
|
||||
file_list config::get_included_files() const {
|
||||
file_list config_ini::get_included_files() const {
|
||||
return m_included;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a deprecation warning if the given parameter is set
|
||||
*/
|
||||
void config::warn_deprecated(const string& section, const string& key, string replacement) const {
|
||||
void config_ini::warn_deprecated(const string& section, const string& key, string replacement) const {
|
||||
if (has(section, key)) {
|
||||
if (replacement.empty()) {
|
||||
m_log.warn(
|
||||
|
@ -76,7 +64,7 @@ void config::warn_deprecated(const string& section, const string& key, string re
|
|||
/**
|
||||
* Returns true if a given parameter exists
|
||||
*/
|
||||
bool config::has(const string& section, const string& key) const {
|
||||
bool config_ini::has(const string& section, const string& key) const {
|
||||
auto it = m_sections.find(section);
|
||||
return it != m_sections.end() && it->second.find(key) != it->second.end();
|
||||
}
|
||||
|
@ -84,7 +72,7 @@ bool config::has(const string& section, const string& key) const {
|
|||
/**
|
||||
* Set parameter value
|
||||
*/
|
||||
void config::set(const string& section, const string& key, string&& value) {
|
||||
void config_ini::set(const string& section, const string& key, string&& value) {
|
||||
auto it = m_sections.find(section);
|
||||
if (it == m_sections.end()) {
|
||||
valuemap_t values;
|
||||
|
@ -108,7 +96,7 @@ void config::set(const string& section, const string& key, string&& value) {
|
|||
* [sub/section]
|
||||
* inherit = section1 section2
|
||||
*/
|
||||
void config::copy_inherited() {
|
||||
void config_ini::copy_inherited() {
|
||||
for (auto&& section : m_sections) {
|
||||
std::vector<string> inherit_sections;
|
||||
|
||||
|
@ -163,7 +151,7 @@ void config::copy_inherited() {
|
|||
/**
|
||||
* Dereference value reference
|
||||
*/
|
||||
string config::dereference(const string& section, const string& key, const string& var) const {
|
||||
string config_ini::dereference(const string& section, const string& key, const string& var) const {
|
||||
if (var.substr(0, 2) != "${" || var.substr(var.length() - 1) != "}") {
|
||||
return var;
|
||||
}
|
||||
|
@ -193,7 +181,7 @@ string config::dereference(const string& section, const string& key, const strin
|
|||
* ${section.key}
|
||||
* ${section.key:fallback}
|
||||
*/
|
||||
string config::dereference_local(string section, const string& key, const string& current_section) const {
|
||||
string config_ini::dereference_local(string section, const string& key, const string& current_section) const {
|
||||
if (section == "BAR") {
|
||||
m_log.warn("${BAR.key} is deprecated. Use ${root.key} instead");
|
||||
}
|
||||
|
@ -222,7 +210,7 @@ string config::dereference_local(string section, const string& key, const string
|
|||
* ${env:key}
|
||||
* ${env:key:fallback value}
|
||||
*/
|
||||
string config::dereference_env(string var) const {
|
||||
string config_ini::dereference_env(string var) const {
|
||||
size_t pos;
|
||||
string env_default;
|
||||
/*
|
||||
|
@ -254,7 +242,7 @@ string config::dereference_env(string var) const {
|
|||
* ${xrdb:key}
|
||||
* ${xrdb:key:fallback value}
|
||||
*/
|
||||
string config::dereference_xrdb(string var) const {
|
||||
string config_ini::dereference_xrdb(string var) const {
|
||||
size_t pos;
|
||||
#if not WITH_XRM
|
||||
m_log.warn("No built-in support to dereference ${xrdb:%s} references (requires `xcb-util-xrm`)", var);
|
||||
|
@ -294,7 +282,7 @@ string config::dereference_xrdb(string var) const {
|
|||
* ${file:/absolute/file/path}
|
||||
* ${file:/absolute/file/path:fallback value}
|
||||
*/
|
||||
string config::dereference_file(string var) const {
|
||||
string config_ini::dereference_file(string var) const {
|
||||
size_t pos;
|
||||
string fallback;
|
||||
bool has_fallback = false;
|
||||
|
@ -316,151 +304,4 @@ string config::dereference_file(string var) const {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
template <>
|
||||
string config::convert(string&& value) const {
|
||||
return forward<string>(value);
|
||||
}
|
||||
|
||||
template <>
|
||||
const char* config::convert(string&& value) const {
|
||||
return value.c_str();
|
||||
}
|
||||
|
||||
template <>
|
||||
char config::convert(string&& value) const {
|
||||
return value.c_str()[0];
|
||||
}
|
||||
|
||||
template <>
|
||||
int config::convert(string&& value) const {
|
||||
return std::strtol(value.c_str(), nullptr, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
short config::convert(string&& value) const {
|
||||
return static_cast<short>(std::strtol(value.c_str(), nullptr, 10));
|
||||
}
|
||||
|
||||
template <>
|
||||
bool config::convert(string&& value) const {
|
||||
string lower{string_util::lower(forward<string>(value))};
|
||||
|
||||
return (lower == "true" || lower == "yes" || lower == "on" || lower == "1");
|
||||
}
|
||||
|
||||
template <>
|
||||
float config::convert(string&& value) const {
|
||||
return std::strtof(value.c_str(), nullptr);
|
||||
}
|
||||
|
||||
template <>
|
||||
double config::convert(string&& value) const {
|
||||
return std::strtod(value.c_str(), nullptr);
|
||||
}
|
||||
|
||||
template <>
|
||||
long config::convert(string&& value) const {
|
||||
return std::strtol(value.c_str(), nullptr, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
long long config::convert(string&& value) const {
|
||||
return std::strtoll(value.c_str(), nullptr, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned char config::convert(string&& value) const {
|
||||
return std::strtoul(value.c_str(), nullptr, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned short config::convert(string&& value) const {
|
||||
return std::strtoul(value.c_str(), nullptr, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned int config::convert(string&& value) const {
|
||||
return std::strtoul(value.c_str(), nullptr, 10);
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned long config::convert(string&& value) const {
|
||||
unsigned long v{std::strtoul(value.c_str(), nullptr, 10)};
|
||||
return v < ULONG_MAX ? v : 0UL;
|
||||
}
|
||||
|
||||
template <>
|
||||
unsigned long long config::convert(string&& value) const {
|
||||
unsigned long long v{std::strtoull(value.c_str(), nullptr, 10)};
|
||||
return v < ULLONG_MAX ? v : 0ULL;
|
||||
}
|
||||
|
||||
template <>
|
||||
spacing_val config::convert(string&& value) const {
|
||||
return units_utils::parse_spacing(value);
|
||||
}
|
||||
|
||||
template <>
|
||||
extent_val config::convert(std::string&& value) const {
|
||||
return units_utils::parse_extent(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows a new format for pixel sizes (like width in the bar section)
|
||||
*
|
||||
* The new format is X%:Z, where X is in [0, 100], and Z is any real value
|
||||
* describing a pixel offset. The actual value is calculated by X% * max + Z
|
||||
*/
|
||||
template <>
|
||||
percentage_with_offset config::convert(string&& value) const {
|
||||
size_t i = value.find(':');
|
||||
|
||||
if (i == std::string::npos) {
|
||||
if (value.find('%') != std::string::npos) {
|
||||
return {std::stod(value), {}};
|
||||
} else {
|
||||
return {0., convert<extent_val>(move(value))};
|
||||
}
|
||||
} else {
|
||||
std::string percentage = value.substr(0, i - 1);
|
||||
return {std::stod(percentage), convert<extent_val>(value.substr(i + 1))};
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
chrono::seconds config::convert(string&& value) const {
|
||||
return chrono::seconds{convert<chrono::seconds::rep>(forward<string>(value))};
|
||||
}
|
||||
|
||||
template <>
|
||||
chrono::milliseconds config::convert(string&& value) const {
|
||||
return chrono::milliseconds{convert<chrono::milliseconds::rep>(forward<string>(value))};
|
||||
}
|
||||
|
||||
template <>
|
||||
chrono::duration<double> config::convert(string&& value) const {
|
||||
return chrono::duration<double>{convert<double>(forward<string>(value))};
|
||||
}
|
||||
|
||||
template <>
|
||||
rgba config::convert(string&& value) const {
|
||||
if (value.empty()) {
|
||||
return rgba{};
|
||||
}
|
||||
|
||||
rgba ret{value};
|
||||
|
||||
if (!ret.has_color()) {
|
||||
throw value_error("\"" + value + "\" is an invalid color value.");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template <>
|
||||
cairo_operator_t config::convert(string&& value) const {
|
||||
return cairo::utils::str2operator(forward<string>(value), CAIRO_OPERATOR_OVER);
|
||||
}
|
||||
|
||||
POLYBAR_NS_END
|
|
@ -0,0 +1,136 @@
|
|||
#include "components/config_lua.hpp"
|
||||
#include "utils/units.hpp"
|
||||
|
||||
POLYBAR_NS
|
||||
|
||||
namespace chrono = std::chrono;
|
||||
|
||||
/**
|
||||
* Get path of loaded file
|
||||
*/
|
||||
const string& config_lua::filepath() const {
|
||||
return m_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the section name of the bar in use
|
||||
*/
|
||||
string config_lua::section() const {
|
||||
return m_barname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a deprecation warning if the given parameter is set
|
||||
*/
|
||||
void config_lua::warn_deprecated(const string& section, const string& key, string replacement) const {
|
||||
if (has(section, key)) {
|
||||
if (replacement.empty()) {
|
||||
m_log.warn(
|
||||
"The config parameter '%s.%s' is deprecated, it will be removed in the future. Please remove it from your "
|
||||
"config",
|
||||
section, key);
|
||||
} else {
|
||||
m_log.warn(
|
||||
"The config parameter `%s.%s` is deprecated, use `%s.%s` instead.", section, key, section, move(replacement));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool config_lua::has(const string& section, const string& key) const {
|
||||
try {
|
||||
pair<sol::table, string> table_message = lua_get_table(section);
|
||||
return config_lua::has(table_message.first, key);
|
||||
} catch (const key_error&) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
file_list config_lua::get_included_files() const {
|
||||
file_list fl{m_file};
|
||||
return fl;
|
||||
}
|
||||
|
||||
template <>
|
||||
bool config_lua::get(const string& section, const string& key) const {
|
||||
return lua_get<bool>(section, key);
|
||||
}
|
||||
|
||||
template <>
|
||||
double config_lua::get(const string& section, const string& key) const {
|
||||
return lua_get<double>(section, key);
|
||||
}
|
||||
|
||||
template <>
|
||||
size_t config_lua::get(const string& section, const string& key) const {
|
||||
return lua_get<size_t>(section, key);
|
||||
}
|
||||
|
||||
template <>
|
||||
int config_lua::get(const string& section, const string& key) const {
|
||||
return lua_get<int>(section, key);
|
||||
}
|
||||
|
||||
pair<string, std::optional<string>> config_lua::get_entries(const string& section) const {
|
||||
if (section == m_barname) {
|
||||
return {BARS_CONTAINER, section};
|
||||
} else if (section == "settings") {
|
||||
return {section, std::nullopt};
|
||||
} else {
|
||||
// split section which should look like "module/xyz" into "modules" and "xyz"
|
||||
return {MODULES_CONTAINER, section.substr(strlen("module/"))};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a given parameter exists in the lua table
|
||||
*/
|
||||
bool config_lua::has(const sol::table& table, const string& key) {
|
||||
for (const pair<sol::object, sol::object> &p: table) {
|
||||
sol::object k = p.first;
|
||||
if (k.is<string>() && k.as<string>() == key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a given parameter exists in the lua table
|
||||
*/
|
||||
bool config_lua::has(const sol::state& table, const string& key) {
|
||||
for (const pair<sol::object, sol::object> &p: table) {
|
||||
sol::object k = p.first;
|
||||
if (k.is<string>() && k.as<string>() == key) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
pair<sol::table, string> config_lua::lua_get_table(const string& section) const {
|
||||
pair<string, std::optional<string>> entries = get_entries(section);
|
||||
|
||||
if (!config_lua::has(m_state, entries.first)) {
|
||||
throw key_error("Missing entry \"" + entries.first + "\"");
|
||||
}
|
||||
sol::optional<sol::table> opt_table = m_state[entries.first];
|
||||
if (opt_table == sol::nullopt) {
|
||||
throw key_error("Wrong type for entry \"" + entries.first + "\": expecting table");
|
||||
}
|
||||
string message_key = entries.first;
|
||||
sol::table table = *opt_table;
|
||||
if (entries.second) {
|
||||
message_key += "[" + *entries.second + "]";
|
||||
if (!config_lua::has(table, *entries.second)) {
|
||||
throw key_error("Missing entry \"" + message_key + "\"");
|
||||
}
|
||||
sol::optional<sol::table> opt_table = table[*entries.second];
|
||||
if (opt_table == sol::nullopt) {
|
||||
throw key_error("Wrong type for entry \"" + message_key + "\": expecting table");
|
||||
}
|
||||
table = *opt_table;
|
||||
}
|
||||
return {table, message_key};
|
||||
}
|
||||
|
||||
POLYBAR_NS_END
|
|
@ -5,6 +5,8 @@
|
|||
#include <cstring>
|
||||
#include <fstream>
|
||||
|
||||
#include "components/config_ini.hpp"
|
||||
#include "components/config_lua.hpp"
|
||||
#include "utils/file.hpp"
|
||||
#include "utils/string.hpp"
|
||||
|
||||
|
@ -15,45 +17,50 @@ config_parser::config_parser(const logger& logger, string&& file)
|
|||
|
||||
config config_parser::parse(string barname) {
|
||||
m_log.notice("Parsing config file: %s", m_config_file);
|
||||
config config(m_log, m_config_file);
|
||||
|
||||
parse_file(m_config_file, {});
|
||||
if (is_lua_file()) {
|
||||
shared_ptr<config_lua> conf_lua = config.make_lua(barname);
|
||||
return config;
|
||||
} else {
|
||||
parse_file(m_config_file, {});
|
||||
|
||||
sectionmap_t sections = create_sectionmap();
|
||||
sectionmap_t sections = create_sectionmap();
|
||||
|
||||
vector<string> bars = get_bars(sections);
|
||||
if (barname.empty()) {
|
||||
if (bars.size() == 1) {
|
||||
barname = bars[0];
|
||||
} else if (bars.empty()) {
|
||||
throw application_error("The config file contains no bar.");
|
||||
} else {
|
||||
throw application_error("The config file contains multiple bars, but no bar name was given. Available bars: " +
|
||||
string_util::join(bars, ", "));
|
||||
vector<string> bars = get_bars(sections);
|
||||
if (barname.empty()) {
|
||||
if (bars.size() == 1) {
|
||||
barname = bars[0];
|
||||
} else if (bars.empty()) {
|
||||
throw application_error("The config file contains no bar.");
|
||||
} else {
|
||||
throw application_error("The config file contains multiple bars, but no bar name was given. Available bars: " +
|
||||
string_util::join(bars, ", "));
|
||||
}
|
||||
} else if (sections.find("bar/" + barname) == sections.end()) {
|
||||
if (bars.empty()) {
|
||||
throw application_error("Undefined bar: " + barname + ". The config file contains no bar.");
|
||||
} else {
|
||||
throw application_error(
|
||||
"Undefined bar: " + barname + ". Available bars: " + string_util::join(get_bars(sections), ", "));
|
||||
}
|
||||
}
|
||||
} else if (sections.find("bar/" + barname) == sections.end()) {
|
||||
if (bars.empty()) {
|
||||
throw application_error("Undefined bar: " + barname + ". The config file contains no bar.");
|
||||
} else {
|
||||
throw application_error(
|
||||
"Undefined bar: " + barname + ". Available bars: " + string_util::join(get_bars(sections), ", "));
|
||||
|
||||
/*
|
||||
* The first element in the files vector is always the main config file and
|
||||
* because it has unique filenames, we can use all the elements from the
|
||||
* second element onwards for the included list
|
||||
*/
|
||||
file_list included(m_files.begin() + 1, m_files.end());
|
||||
shared_ptr<config_ini> conf_ini = config.make_ini(barname);
|
||||
|
||||
conf_ini->set_sections(move(sections));
|
||||
conf_ini->set_included(move(included));
|
||||
if (use_xrm) {
|
||||
conf_ini->use_xrm();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The first element in the files vector is always the main config file and
|
||||
* because it has unique filenames, we can use all the elements from the
|
||||
* second element onwards for the included list
|
||||
*/
|
||||
file_list included(m_files.begin() + 1, m_files.end());
|
||||
config conf(m_log, move(m_config_file), move(barname));
|
||||
|
||||
conf.set_sections(move(sections));
|
||||
conf.set_included(move(included));
|
||||
if (use_xrm) {
|
||||
conf.use_xrm();
|
||||
}
|
||||
|
||||
return conf;
|
||||
return config;
|
||||
}
|
||||
|
||||
sectionmap_t config_parser::create_sectionmap() {
|
||||
|
@ -98,8 +105,8 @@ sectionmap_t config_parser::create_sectionmap() {
|
|||
vector<string> config_parser::get_bars(const sectionmap_t& sections) const {
|
||||
vector<string> bars;
|
||||
for (const auto& it : sections) {
|
||||
if (it.first.find(config::BAR_PREFIX) == 0) {
|
||||
bars.push_back(it.first.substr(strlen(config::BAR_PREFIX)));
|
||||
if (it.first.find(config_ini::BAR_PREFIX) == 0) {
|
||||
bars.push_back(it.first.substr(strlen(config_ini::BAR_PREFIX)));
|
||||
}
|
||||
}
|
||||
return bars;
|
||||
|
@ -309,6 +316,10 @@ bool config_parser::is_valid_name(const string& name) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool config_parser::is_lua_file() const {
|
||||
return m_config_file.substr(m_config_file.size() - 4) == ".lua";
|
||||
}
|
||||
|
||||
string config_parser::parse_escaped_value(const line_t& line, string&& value, const string& key) {
|
||||
string cfg_value = value;
|
||||
bool log = false;
|
||||
|
|
|
@ -28,6 +28,7 @@ namespace modules {
|
|||
// Load configuration values
|
||||
m_mapped = m_conf.get(name(), "mapped", m_mapped);
|
||||
m_interval = m_conf.get(name(), "interval", m_interval);
|
||||
m_unmute_on_scroll = m_conf.get(name(), "unmute-on-scroll", m_unmute_on_scroll);
|
||||
|
||||
auto master_mixer_name = m_conf.get(name(), "master-mixer", "Master"s);
|
||||
auto speaker_mixer_name = m_conf.get(name(), "speaker-mixer", ""s);
|
||||
|
@ -261,6 +262,9 @@ namespace modules {
|
|||
}
|
||||
const auto& mixers = get_mixers();
|
||||
for (auto&& mixer : mixers) {
|
||||
if (m_unmute_on_scroll) {
|
||||
mixer->set_mute(true);
|
||||
}
|
||||
m_mapped ? mixer->set_normalized_volume(math_util::cap<float>(mixer->get_normalized_volume() + interval, 0, 100))
|
||||
: mixer->set_volume(math_util::cap<float>(mixer->get_volume() + interval, 0, 100));
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace modules {
|
|||
|
||||
// Load configuration values
|
||||
m_interval = m_conf.get(name(), "interval", m_interval);
|
||||
m_unmute_on_scroll = m_conf.get(name(), "unmute-on-scroll", m_unmute_on_scroll);
|
||||
|
||||
auto sink_name = m_conf.get(name(), "sink", ""s);
|
||||
bool m_max_volume = m_conf.get(name(), "use-ui-max", true);
|
||||
|
@ -156,10 +157,16 @@ namespace modules {
|
|||
}
|
||||
|
||||
void pulseaudio_module::action_inc() {
|
||||
if (m_unmute_on_scroll) {
|
||||
m_pulseaudio->set_mute(false);
|
||||
}
|
||||
m_pulseaudio->inc_volume(m_interval);
|
||||
}
|
||||
|
||||
void pulseaudio_module::action_dec() {
|
||||
if (m_unmute_on_scroll) {
|
||||
m_pulseaudio->set_mute(false);
|
||||
}
|
||||
m_pulseaudio->inc_volume(-m_interval);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue