Merge branch 'Alexays:master' into master

pull/2322/head
Tuur Vanhoutte 2023-07-23 14:30:14 +02:00 committed by GitHub
commit 2f04a49129
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 270 additions and 28 deletions

View File

@ -41,6 +41,7 @@ class Workspaces : public AModule, public sigc::trackable {
const Bar& bar_; const Bar& bar_;
std::vector<Json::Value> workspaces_; std::vector<Json::Value> workspaces_;
std::vector<std::string> high_priority_named_;
std::vector<std::string> workspaces_order_; std::vector<std::string> workspaces_order_;
Gtk::Box box_; Gtk::Box box_;
util::JsonParser parser_; util::JsonParser parser_;

View File

@ -95,6 +95,7 @@ class SleeperThread {
} }
~SleeperThread() { ~SleeperThread() {
connection_.disconnect();
stop(); stop();
if (thread_.joinable()) { if (thread_.joinable()) {
thread_.join(); thread_.join();

View File

@ -0,0 +1,182 @@
waybar-cava(5) "waybar-cava" "User Manual"
# NAME
cava
# DESCRIPTION
*cava* module for karlstav/cava project. See it on github: https://github.com/karlstav/cava.
# FILES
$XDG_CONFIG_HOME/waybar/config ++
Per user configuration file
# ADDITIONAL FILES
libcava lives in:
. /usr/lib/libcava.so or /usr/lib64/libcava.so
. /usr/lib/pkgconfig/cava.pc or /usr/lib64/pkgconfig/cava.pc
. /usr/include/cava
# CONFIGURATION
[- *Option*
:- *Typeof*
:- *Default*
:- *Description*
|[ *cava_config*
:[ string
:[
:< Path where cava configuration file is placed to
|[ *framerate*
:[ integer
:[ 30
:[ rames per second. Is used as a replacement for *interval*
|[ *autosens*
:[ integer
:[ 1
:[ Will attempt to decrease sensitivity if the bars peak
|[ *sensitivity*
:[ integer
:[ 100
:[ Manual sensitivity in %. It's recommended to be omitted when *autosens* = 1
|[ *bars*
:[ integer
:[ 12
:[ The number of bars
|[ *lower_cutoff_freq*
:[ long integer
:[ 50
:[ Lower cutoff frequencies for lowest bars the bandwidth of the visualizer
|[ *higher_cutoff_freq*
:[ long integer
:[ 10000
:[ Higher cutoff frequencies for highest bars the bandwidth of the visualizer
|[ *sleep_timer*
:[ integer
:[ 5
:[ Seconds with no input before cava main thread goes to sleep mode
|[ *method*
:[ string
:[ pulse
:[ Audio capturing method. Possible methods are: pipewire, pulse, alsa, fifo, sndio or shmem
|[ *source*
:[ string
:[ auto
:[ See cava configuration
|[ *sample_rate*
:[ long integer
:[ 44100
:[ See cava configuration
|[ *sample_bits*
:[ integer
:[ 16
:[ See cava configuration
|[ *stereo*
:[ bool
:[ true
:[ Visual channels
|[ *reverse*
:[ bool
:[ false
:[ Displays frequencies the other way around
|[ *bar_delimiter*
:[ integer
:[ 0
:[ Each bar is separated by a delimiter. Use decimal value in ascii table(i.e. 59 = ";"). 0 means no delimiter
|[ *monstercat*
:[ bool
:[ false
:[ Disables or enables the so-called "Monstercat smoothing" with of without "waves"
|[ *waves*
:[ bool
:[ false
:[ Disables or enables the so-called "Monstercat smoothing" with of without "waves"
|[ *noise_reduction*
:[ double
:[ 0.77
:[ Range between 0 - 1. The raw visualization is very noisy, this factor adjust the integral and gravity filters to keep the signal smooth. 1 - will be very slow and smooth, 0 - will be fast but noisy
|[ *input_delay*
:[ integer
:[ 2
:[ Sets the delay before fetching audio source thread start working. On author machine Waybar starts much faster then pipewire audio server, and without a little delay cava module fails due to pipewire is not ready
|[ *ascii_max_range*
:[ integer
:[ 7
:[ It's impossible to set it directly. The value is dictated by the number of icons in the array *format-icons*
|[ *data_format*
:[ string
:[ asci
:[ It's impossible to set it. Waybar sets it to = asci for internal needs
|[ *raw_target*
:[ string
:[ /dev/stdout
:[ It's impossible to set it. Waybar sets it to = /dev/stdout for internal needs
Configuration can be provided as:
- The only cava configuration file which is provided through *cava_config*. The rest configuration can be skipped
- Without cava configuration file. In such case cava should be configured through provided list of the configuration option
- Mix. When provided both And cava configuration file And configuration options. In such case waybar applies configuration file first then overrides particular options by the provided list of configuration options
# ACTIONS
[- *String*
:- *Action*
|[ *mode*
:< Switch main cava thread and fetching audio source thread from/to pause/resume
# DEPENDENCIES
- iniparser
- fftw3
# SOLVING ISSUES
. On start Waybar throws an exception "error while loading shared libraries: libcava.so: cannot open shared object file: No such file or directory".
It might happen when libcava for some reason hasn't been registered in the system. sudo ldconfig should help
. Waybar is starting but cava module doesn't react on the music
1. In such case for at first need to make sure usual cava application is working as well
2. If so, need to comment all configuration options. Uncomment cava_config and provide the path to the working cava config
3. You might set too huge or too small input_delay. Try to setup to 4 seconds, restart waybar and check again 4 seconds past. Usual even on weak machines it should be enough
4. You might accidentally switched action mode to pause mode
# RISING ISSUES
For clear understanding: this module is a cava API's consumer. So for any bugs related to cava engine you should contact to Cava upstream(https://github.com/karlstav/cava) ++
with the one Exception. Cava upstream doesn't provide cava as a shared library. For that this module author made a fork libcava(https://github.com/LukashonakV/cava). ++
So the order is:
. cava upstream
. libcava upstream.
In case when cava releases new version and you're wanna get it, it should be raised an issue to libcava(https://github.com/LukashonakV/cava) with title ++
\[Bump\]x.x.x where x.x.x is cava release version.
# EXAMPLES
```
"cava": {
// "cava_config": "$XDG_CONFIG_HOME/cava/cava.conf",
"framerate": 30,
"autosens": 1,
// "sensitivity": 100,
"bars": 14,
"lower_cutoff_freq": 50,
"higher_cutoff_freq": 10000,
"method": "pulse",
"source": "auto",
"stereo": true,
"reverse": false,
"bar_delimiter": 0,
"monstercat": false,
"waves": false,
"noise_reduction": 0.77,
"input_delay": 2,
"format-icons" : ["▁", "▂", "▃", "▄", "▅", "▆", "▇", "█" ],
"actions": {
"on-click-right": "mode"
}
},
```

View File

@ -63,7 +63,7 @@ Invalid expressions (e.g., mismatched parentheses) are skipped.
# STYLE # STYLE
- *#window* - *#window*
- *#window.empty* When no windows are in the workspace - *window#waybar.empty #window* When no windows are in the workspace
The following classes are applied to the entire Waybar rather than just the The following classes are applied to the entire Waybar rather than just the
window widget: window widget:

View File

@ -102,6 +102,7 @@ Additional to workspace name matching, the following *format-icons* can be set.
- *urgent*: Will be shown, when workspace is flagged as urgent - *urgent*: Will be shown, when workspace is flagged as urgent
- *focused*: Will be shown, when workspace is focused - *focused*: Will be shown, when workspace is focused
- *persistent*: Will be shown, when workspace is persistent one. - *persistent*: Will be shown, when workspace is persistent one.
- *high-priority-named*: Icons by names will be shown always for that workspaces, independent by state.
# PERSISTENT WORKSPACES # PERSISTENT WORKSPACES
@ -134,6 +135,7 @@ n.b.: the list of outputs can be obtained from command line using *swaymsg -t ge
"3": "", "3": "",
"4": "", "4": "",
"5": "", "5": "",
"high-priority-named": [ "1", "2" ],
"urgent": "", "urgent": "",
"focused": "", "focused": "",
"default": "" "default": ""

View File

@ -89,7 +89,7 @@ Addressed by *wlr/taskbar*
*{icon}*: The icon of the application. *{icon}*: The icon of the application.
*{title}*: The application name as in desktop file if appropriate desktop fils found, otherwise same as {app_id} *{name}*: The application name as in desktop file if appropriate desktop fils found, otherwise same as {app_id}
*{title}*: The title of the application. *{title}*: The title of the application.

View File

@ -268,6 +268,7 @@ Valid options for the (optional) "orientation" property are: "horizontal", "vert
- *waybar-backlight(5)* - *waybar-backlight(5)*
- *waybar-battery(5)* - *waybar-battery(5)*
- *waybar-bluetooth(5)* - *waybar-bluetooth(5)*
- *waybar-cava(5)*
- *waybar-clock(5)* - *waybar-clock(5)*
- *waybar-cpu(5)* - *waybar-cpu(5)*
- *waybar-custom(5)* - *waybar-custom(5)*

View File

@ -1,6 +1,6 @@
project( project(
'waybar', 'cpp', 'c', 'waybar', 'cpp', 'c',
version: '0.9.19', version: '0.9.20',
license: 'MIT', license: 'MIT',
meson_version: '>= 0.50.0', meson_version: '>= 0.50.0',
default_options : [ default_options : [
@ -346,7 +346,7 @@ if get_option('experimental')
endif endif
cava = dependency('cava', cava = dependency('cava',
version : '>=0.8.4', version : '>=0.8.5',
required: get_option('cava'), required: get_option('cava'),
fallback : ['cava', 'cava_dep'], fallback : ['cava', 'cava_dep'],
not_found_message: 'cava is not found. Building waybar without cava') not_found_message: 'cava is not found. Building waybar without cava')
@ -423,6 +423,7 @@ if scdoc.found()
main_manpage_path, main_manpage_path,
'waybar-backlight.5.scd', 'waybar-backlight.5.scd',
'waybar-battery.5.scd', 'waybar-battery.5.scd',
'waybar-cava.5.scd',
'waybar-clock.5.scd', 'waybar-clock.5.scd',
'waybar-cpu.5.scd', 'waybar-cpu.5.scd',
'waybar-custom.5.scd', 'waybar-custom.5.scd',

View File

@ -38,7 +38,10 @@ auto Language::update() -> void {
std::lock_guard<std::mutex> lg(mutex_); std::lock_guard<std::mutex> lg(mutex_);
std::string layoutName = std::string{}; std::string layoutName = std::string{};
if (config_.isMember("format-" + layout_.short_description)) { if (config_.isMember("format-" + layout_.short_description + "-" + layout_.variant)) {
const auto propName = "format-" + layout_.short_description + "-" + layout_.variant;
layoutName = fmt::format(fmt::runtime(format_), config_[propName].asString());
} else if (config_.isMember("format-" + layout_.short_description)) {
const auto propName = "format-" + layout_.short_description; const auto propName = "format-" + layout_.short_description;
layoutName = fmt::format(fmt::runtime(format_), config_[propName].asString()); layoutName = fmt::format(fmt::runtime(format_), config_[propName].asString());
} else { } else {

View File

@ -48,14 +48,7 @@ auto Window::update() -> void {
std::string window_name = waybar::util::sanitize_string(workspace_.last_window_title); std::string window_name = waybar::util::sanitize_string(workspace_.last_window_title);
std::string window_address = workspace_.last_window; std::string window_address = workspace_.last_window;
if (window_name != window_data_.title) { window_data_.title = window_name;
if (window_name.empty()) {
label_.get_style_context()->add_class("empty");
} else {
label_.get_style_context()->remove_class("empty");
}
window_data_.title = window_name;
}
if (!format_.empty()) { if (!format_.empty()) {
label_.show(); label_.show();

View File

@ -145,6 +145,40 @@ std::pair<int, int> leafNodesInWorkspace(const Json::Value& node) {
return {sum, floating_sum}; return {sum, floating_sum};
} }
std::optional<std::reference_wrapper<const Json::Value>> getSingleChildNode(
const Json::Value& node) {
auto const& nodes = node["nodes"];
if (nodes.empty()) {
if (node["type"].asString() == "workspace")
return {};
else if (node["type"].asString() == "floating_con") {
return {};
} else {
return {std::cref(node)};
}
}
auto it = std::cbegin(nodes);
if (it == std::cend(nodes)) {
return {};
}
auto const& child = *it;
++it;
if (it != std::cend(nodes)) {
return {};
}
return {getSingleChildNode(child)};
}
std::tuple<std::string, std::string, std::string> getWindowInfo(const Json::Value& node) {
const auto app_id = node["app_id"].isString() ? node["app_id"].asString()
: node["window_properties"]["instance"].asString();
const auto app_class = node["window_properties"]["class"].isString()
? node["window_properties"]["class"].asString()
: "";
const auto shell = node["shell"].isString() ? node["shell"].asString() : "";
return {app_id, app_class, shell};
}
std::tuple<std::size_t, int, int, std::string, std::string, std::string, std::string, std::string> std::tuple<std::size_t, int, int, std::string, std::string, std::string, std::string, std::string>
gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Value& config_, gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Value& config_,
const Bar& bar_, Json::Value& parentWorkspace, const Bar& bar_, Json::Value& parentWorkspace,
@ -181,12 +215,7 @@ gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Valu
// found node // found node
spdlog::trace("actual output {}, output found {}, node (focused) found {}", bar_.output->name, spdlog::trace("actual output {}, output found {}, node (focused) found {}", bar_.output->name,
output, node["name"].asString()); output, node["name"].asString());
auto app_id = node["app_id"].isString() ? node["app_id"].asString() const auto [app_id, app_class, shell] = getWindowInfo(node);
: node["window_properties"]["instance"].asString();
const auto app_class = node["window_properties"]["class"].isString()
? node["window_properties"]["class"].asString()
: "";
const auto shell = node["shell"].isString() ? node["shell"].asString() : "";
int nb = node.size(); int nb = node.size();
int floating_count = 0; int floating_count = 0;
std::string workspace_layout = ""; std::string workspace_layout = "";
@ -226,15 +255,24 @@ gfnWithWorkspace(const Json::Value& nodes, std::string& output, const Json::Valu
std::pair all_leaf_nodes = leafNodesInWorkspace(immediateParent); std::pair all_leaf_nodes = leafNodesInWorkspace(immediateParent);
// using an empty string as default ensures that no window depending styles are set due to the // using an empty string as default ensures that no window depending styles are set due to the
// checks above for !name.empty() // checks above for !name.empty()
std::string app_id = "";
std::string app_class = "";
std::string workspace_layout = "";
if (all_leaf_nodes.first == 1) {
const auto single_child = getSingleChildNode(immediateParent);
if (single_child.has_value()) {
std::tie(app_id, app_class, workspace_layout) = getWindowInfo(single_child.value());
}
}
return {all_leaf_nodes.first, return {all_leaf_nodes.first,
all_leaf_nodes.second, all_leaf_nodes.second,
0, 0,
(all_leaf_nodes.first > 0 || all_leaf_nodes.second > 0) (all_leaf_nodes.first > 0 || all_leaf_nodes.second > 0)
? config_["offscreen-css-text"].asString() ? config_["offscreen-css-text"].asString()
: "", : "",
"", app_id,
"", app_class,
"", workspace_layout,
immediateParent["layout"].asString()}; immediateParent["layout"].asString()};
} }

View File

@ -28,6 +28,11 @@ Workspaces::Workspaces(const std::string &id, const Bar &bar, const Json::Value
: AModule(config, "workspaces", id, false, !config["disable-scroll"].asBool()), : AModule(config, "workspaces", id, false, !config["disable-scroll"].asBool()),
bar_(bar), bar_(bar),
box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0) { box_(bar.vertical ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL, 0) {
if (config["format-icons"]["high-priority-named"].isArray()) {
for (auto &it : config["format-icons"]["high-priority-named"]) {
high_priority_named_.push_back(it.asString());
}
}
box_.set_name("workspaces"); box_.set_name("workspaces");
if (!id.empty()) { if (!id.empty()) {
box_.get_style_context()->add_class(id); box_.get_style_context()->add_class(id);
@ -279,9 +284,24 @@ Gtk::Button &Workspaces::addButton(const Json::Value &node) {
} }
std::string Workspaces::getIcon(const std::string &name, const Json::Value &node) { std::string Workspaces::getIcon(const std::string &name, const Json::Value &node) {
std::vector<std::string> keys = {"urgent", "focused", name, "visible", "default"}; std::vector<std::string> keys = {"high-priority-named", "urgent", "focused", name, "default"};
for (auto const &key : keys) { for (auto const &key : keys) {
if (key == "focused" || key == "visible" || key == "urgent") { if (key == "high-priority-named") {
auto it = std::find_if(high_priority_named_.begin(), high_priority_named_.end(),
[&](const std::string &member) { return member == name; });
if (it != high_priority_named_.end()) {
return config_["format-icons"][name].asString();
}
it = std::find_if(high_priority_named_.begin(), high_priority_named_.end(),
[&](const std::string &member) {
return trimWorkspaceName(member) == trimWorkspaceName(name);
});
if (it != high_priority_named_.end()) {
return config_["format-icons"][trimWorkspaceName(name)].asString();
}
}
if (key == "focused" || key == "urgent") {
if (config_["format-icons"][key].isString() && node[key].asBool()) { if (config_["format-icons"][key].isString() && node[key].asBool()) {
return config_["format-icons"][key].asString(); return config_["format-icons"][key].asString();
} }

View File

@ -1,7 +1,7 @@
[wrap-file] [wrap-file]
directory = cava-0.8.4 directory = cava-0.8.5
source_url = https://github.com/LukashonakV/cava/archive/0.8.4.tar.gz source_url = https://github.com/LukashonakV/cava/archive/0.8.5.tar.gz
source_filename = cava-0.8.4.tar.gz source_filename = cava-0.8.5.tar.gz
source_hash = 523353f446570277d40b8e1efb84468d70fdec53e1356a555c14bf466557a3ed source_hash = 9ce3df7d374dc83ed0704fe3caef5e00600ce061d85608aad4142d2c59aa4647
[provide] [provide]
cava = cava_dep cava = cava_dep