Compare commits

...

8 Commits

Author SHA1 Message Date
dvermd 751ac7a5cc
Merge b5070bbc32 into 11b522c313 2024-01-17 10:25:37 -08:00
Roddy Rappaport 11b522c313 doc: Added unmute-on-scroll to changelog and module descriptions 2024-01-17 18:01:10 +01:00
Roddy Rappaport 82a81ce07c feat(pulseaudio): Add unmute on scroll option (polybar#3067)
This will allow users to specify in their config if they want the mixers
to unmute if they use the scroll wheel on the module.

Closes: #3067
2024-01-17 18:01:10 +01:00
Roddy Rappaport c2dd279bf7 feat(alsa): Add unmute on scroll option (polybar#3067)
This will allow users to specify in their config if they want the mixers
to unmute if they use the scroll wheel on the module.
2024-01-17 18:01:10 +01:00
patrick96 174ce34285 fix(doc): Update vulnerable rtd search extension
Ref: https://github.com/readthedocs/readthedocs-sphinx-search/security/advisories/GHSA-xgfm-fjx6-62mj
2024-01-16 22:37:15 +01:00
dvermd b5070bbc32 working minimal lua config implementation using sol2 wrapper 2023-05-22 22:24:07 +02:00
dvermd c9bba89d52 create config wrapper 2023-05-22 22:05:19 +02:00
dvermd 9ff6d0cb10 rename config to config_ini 2023-05-22 22:05:19 +02:00
24 changed files with 31416 additions and 384 deletions

View File

@ -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

50
doc/config.lua Normal file
View File

@ -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"
}
}

View File

@ -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

View File

@ -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.

View File

@ -4,6 +4,7 @@
#include <set>
#include "common.hpp"
#include "components/config.hpp"
#include "components/eventloop.hpp"
#include "components/types.hpp"
#include "errors.hpp"

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
/**

View File

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

View File

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

View File

@ -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()
# }}}

20
lib/sol2/LICENSE.txt Normal file
View File

@ -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.

53
lib/sol2/sol/config.hpp Normal file
View File

@ -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

1321
lib/sol2/sol/forward.hpp Normal file

File diff suppressed because it is too large Load Diff

28907
lib/sol2/sol/sol.hpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -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++)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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));
}

View File

@ -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);
}