commit
4deb6d812d
|
@ -67,6 +67,9 @@
|
||||||
#include "modules/bluetooth.hpp"
|
#include "modules/bluetooth.hpp"
|
||||||
#include "modules/inhibitor.hpp"
|
#include "modules/inhibitor.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_LIBJACK
|
||||||
|
#include "modules/jack.hpp"
|
||||||
|
#endif
|
||||||
#include "bar.hpp"
|
#include "bar.hpp"
|
||||||
#include "modules/custom.hpp"
|
#include "modules/custom.hpp"
|
||||||
#include "modules/temperature.hpp"
|
#include "modules/temperature.hpp"
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fmt/format.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <jack/jack.h>
|
||||||
|
#include <jack/thread.h>
|
||||||
|
#include "ALabel.hpp"
|
||||||
|
#include "util/sleeper_thread.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules {
|
||||||
|
|
||||||
|
class JACK : public ALabel {
|
||||||
|
public:
|
||||||
|
JACK(const std::string&, const Json::Value&);
|
||||||
|
~JACK() = default;
|
||||||
|
auto update() -> void;
|
||||||
|
|
||||||
|
int bufSize(jack_nframes_t size);
|
||||||
|
int sampleRate(jack_nframes_t rate);
|
||||||
|
int xrun();
|
||||||
|
void shutdown();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string JACKState();
|
||||||
|
|
||||||
|
jack_client_t* client_;
|
||||||
|
jack_nframes_t bufsize_;
|
||||||
|
jack_nframes_t samplerate_;
|
||||||
|
unsigned int xruns_;
|
||||||
|
float load_;
|
||||||
|
bool running_;
|
||||||
|
std::mutex mutex_;
|
||||||
|
std::string state_;
|
||||||
|
util::SleeperThread thread_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules
|
||||||
|
|
||||||
|
int bufSizeCallback(jack_nframes_t size, void *obj);
|
||||||
|
int sampleRateCallback(jack_nframes_t rate, void *obj);
|
||||||
|
int xrunCallback(void *obj);
|
||||||
|
void shutdownCallback(void *obj);
|
|
@ -0,0 +1,112 @@
|
||||||
|
waybar-jack(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - JACK module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *jack* module displays the current state of the JACK server.
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
Addressed by *jack*
|
||||||
|
|
||||||
|
*format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: *{load}%* ++
|
||||||
|
The format, how information should be displayed. This format is used when other formats aren't specified.
|
||||||
|
|
||||||
|
*format-connected*: ++
|
||||||
|
typeof: string ++
|
||||||
|
This format is used when the module is connected to the JACK server.
|
||||||
|
|
||||||
|
*format-disconnected*: ++
|
||||||
|
typeof: string ++
|
||||||
|
This format is used when the module is not connected to the JACK server.
|
||||||
|
|
||||||
|
*format-xrun*: ++
|
||||||
|
typeof: string ++
|
||||||
|
This format is used for one polling interval, when the JACK server reports an xrun.
|
||||||
|
|
||||||
|
*realtime*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: *true* ++
|
||||||
|
Option to drop real-time privileges for the JACK client opened by Waybar.
|
||||||
|
|
||||||
|
*tooltip*: ++
|
||||||
|
typeof: bool ++
|
||||||
|
default: *true* ++
|
||||||
|
Option to disable tooltip on hover.
|
||||||
|
|
||||||
|
*tooltip-format*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: *{bufsize}/{samplerate} {latency}ms* ++
|
||||||
|
The format of information displayed in the tooltip.
|
||||||
|
|
||||||
|
*interval*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
default: 1 ++
|
||||||
|
The interval in which the information gets polled.
|
||||||
|
|
||||||
|
*rotate*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
Positive value to rotate the text label.
|
||||||
|
|
||||||
|
*max-length*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
The maximum length in character the module should display.
|
||||||
|
|
||||||
|
*min-length*: ++
|
||||||
|
typeof: integer ++
|
||||||
|
The minimum length in characters the module should take up.
|
||||||
|
|
||||||
|
*align*: ++
|
||||||
|
typeof: float ++
|
||||||
|
The alignment of the text, where 0 is left-aligned and 1 is right-aligned. If the module is rotated, it will follow the flow of the text.
|
||||||
|
|
||||||
|
*on-click*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when clicked on the module.
|
||||||
|
|
||||||
|
*on-click-middle*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when middle-clicked on the module using mousewheel.
|
||||||
|
|
||||||
|
*on-click-right*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when you right clicked on the module.
|
||||||
|
|
||||||
|
*on-update*: ++
|
||||||
|
typeof: string ++
|
||||||
|
Command to execute when the module is updated.
|
||||||
|
|
||||||
|
# FORMAT REPLACEMENTS
|
||||||
|
|
||||||
|
*{load}*: The current CPU load estimated by JACK.
|
||||||
|
|
||||||
|
*{bufsize}*: The size of the JACK buffer.
|
||||||
|
|
||||||
|
*{samplerate}*: The samplerate at which the JACK server is running.
|
||||||
|
|
||||||
|
*{latency}*: The duration, in ms, of the current buffer size.
|
||||||
|
|
||||||
|
*{xruns}*: The number of xruns reported by the JACK server since starting Waybar.
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
```
|
||||||
|
"jack": {
|
||||||
|
"format": "DSP {}%",
|
||||||
|
"format-xrun": "{xruns} xruns",
|
||||||
|
"format-disconnected": "DSP off",
|
||||||
|
"realtime": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# STYLE
|
||||||
|
|
||||||
|
- *#jack*
|
||||||
|
- *#jack.connected*
|
||||||
|
- *#jack.disconnected*
|
||||||
|
- *#jack.xrun*
|
|
@ -98,6 +98,7 @@ libudev = dependency('libudev', required: get_option('libudev'))
|
||||||
libevdev = dependency('libevdev', required: get_option('libevdev'))
|
libevdev = dependency('libevdev', required: get_option('libevdev'))
|
||||||
libmpdclient = dependency('libmpdclient', required: get_option('mpd'))
|
libmpdclient = dependency('libmpdclient', required: get_option('mpd'))
|
||||||
xkbregistry = dependency('xkbregistry')
|
xkbregistry = dependency('xkbregistry')
|
||||||
|
libjack = dependency('jack', required: get_option('jack'))
|
||||||
|
|
||||||
libsndio = compiler.find_library('sndio', required: get_option('sndio'))
|
libsndio = compiler.find_library('sndio', required: get_option('sndio'))
|
||||||
if libsndio.found()
|
if libsndio.found()
|
||||||
|
@ -228,6 +229,11 @@ if libpulse.found()
|
||||||
src_files += 'src/modules/pulseaudio.cpp'
|
src_files += 'src/modules/pulseaudio.cpp'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if libjack.found()
|
||||||
|
add_project_arguments('-DHAVE_LIBJACK', language: 'cpp')
|
||||||
|
src_files += 'src/modules/jack.cpp'
|
||||||
|
endif
|
||||||
|
|
||||||
if dbusmenu_gtk.found()
|
if dbusmenu_gtk.found()
|
||||||
add_project_arguments('-DHAVE_DBUSMENU', language: 'cpp')
|
add_project_arguments('-DHAVE_DBUSMENU', language: 'cpp')
|
||||||
src_files += files(
|
src_files += files(
|
||||||
|
@ -308,6 +314,7 @@ executable(
|
||||||
libnlgen,
|
libnlgen,
|
||||||
upower_glib,
|
upower_glib,
|
||||||
libpulse,
|
libpulse,
|
||||||
|
libjack,
|
||||||
libudev,
|
libudev,
|
||||||
libepoll,
|
libepoll,
|
||||||
libmpdclient,
|
libmpdclient,
|
||||||
|
|
|
@ -14,3 +14,4 @@ option('sndio', type: 'feature', value: 'auto', description: 'Enable support for
|
||||||
option('logind', type: 'feature', value: 'auto', description: 'Enable support for logind')
|
option('logind', type: 'feature', value: 'auto', description: 'Enable support for logind')
|
||||||
option('tests', type: 'feature', value: 'auto', description: 'Enable tests')
|
option('tests', type: 'feature', value: 'auto', description: 'Enable tests')
|
||||||
option('experimental', type : 'boolean', value : false, description: 'Enable experimental features')
|
option('experimental', type : 'boolean', value : false, description: 'Enable experimental features')
|
||||||
|
option('jack', type: 'feature', value: 'auto', description: 'Enable support for JACK')
|
||||||
|
|
|
@ -123,6 +123,11 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
||||||
if (ref == "inhibitor") {
|
if (ref == "inhibitor") {
|
||||||
return new waybar::modules::Inhibitor(id, bar_, config_[name]);
|
return new waybar::modules::Inhibitor(id, bar_, config_[name]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_LIBJACK
|
||||||
|
if (ref == "jack") {
|
||||||
|
return new waybar::modules::JACK(id, config_[name]);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
if (ref == "temperature") {
|
if (ref == "temperature") {
|
||||||
return new waybar::modules::Temperature(id, config_[name]);
|
return new waybar::modules::Temperature(id, config_[name]);
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
#include "modules/jack.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules {
|
||||||
|
|
||||||
|
JACK::JACK(const std::string &id, const Json::Value &config)
|
||||||
|
: ALabel(config, "jack", id, "{load}%", 1) {
|
||||||
|
running_ = false;
|
||||||
|
client_ = NULL;
|
||||||
|
|
||||||
|
thread_ = [this] {
|
||||||
|
dp.emit();
|
||||||
|
thread_.sleep_for(interval_);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string JACK::JACKState() {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
if (running_) {
|
||||||
|
load_ = jack_cpu_load(client_);
|
||||||
|
return state_;
|
||||||
|
}
|
||||||
|
|
||||||
|
xruns_ = 0;
|
||||||
|
load_ = 0;
|
||||||
|
bufsize_ = 0;
|
||||||
|
samplerate_ = 0;
|
||||||
|
|
||||||
|
if (client_) {
|
||||||
|
jack_client_close(client_);
|
||||||
|
client_ = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
client_ = jack_client_open("waybar", JackNoStartServer, NULL);
|
||||||
|
if (!client_) return "disconnected";
|
||||||
|
|
||||||
|
if (config_["realtime"].isBool() && !config_["realtime"].asBool()) {
|
||||||
|
pthread_t jack_thread = jack_client_thread_id(client_);
|
||||||
|
jack_drop_real_time_scheduling(jack_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
bufsize_ = jack_get_buffer_size(client_);
|
||||||
|
samplerate_ = jack_get_sample_rate(client_);
|
||||||
|
jack_set_sample_rate_callback(client_, sampleRateCallback, this);
|
||||||
|
jack_set_buffer_size_callback(client_, bufSizeCallback, this);
|
||||||
|
jack_set_xrun_callback(client_, xrunCallback, this);
|
||||||
|
jack_on_shutdown(client_, shutdownCallback, this);
|
||||||
|
if (jack_activate(client_)) return "disconnected";
|
||||||
|
|
||||||
|
running_ = true;
|
||||||
|
return "connected";
|
||||||
|
}
|
||||||
|
|
||||||
|
auto JACK::update() -> void {
|
||||||
|
std::string format;
|
||||||
|
std::string state = JACKState();
|
||||||
|
float latency = 1000 * (float)bufsize_ / (float)samplerate_;
|
||||||
|
|
||||||
|
if (label_.get_style_context()->has_class("xrun")) {
|
||||||
|
label_.get_style_context()->remove_class("xrun");
|
||||||
|
state = "connected";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (label_.get_style_context()->has_class(state_))
|
||||||
|
label_.get_style_context()->remove_class(state_);
|
||||||
|
label_.get_style_context()->add_class(state);
|
||||||
|
state_ = state;
|
||||||
|
|
||||||
|
if (config_["format-" + state].isString()) {
|
||||||
|
format = config_["format-" + state].asString();
|
||||||
|
} else if (config_["format"].isString()) {
|
||||||
|
format = config_["format"].asString();
|
||||||
|
} else
|
||||||
|
format = "{load}%";
|
||||||
|
|
||||||
|
label_.set_markup(fmt::format(format, fmt::arg("load", std::round(load_)),
|
||||||
|
fmt::arg("bufsize", bufsize_), fmt::arg("samplerate", samplerate_),
|
||||||
|
fmt::arg("latency", fmt::format("{:.2f}", latency)),
|
||||||
|
fmt::arg("xruns", xruns_)));
|
||||||
|
|
||||||
|
if (tooltipEnabled()) {
|
||||||
|
std::string tooltip_format = "{bufsize}/{samplerate} {latency}ms";
|
||||||
|
if (config_["tooltip-format"].isString()) tooltip_format = config_["tooltip-format"].asString();
|
||||||
|
label_.set_tooltip_text(fmt::format(
|
||||||
|
tooltip_format, fmt::arg("load", std::round(load_)), fmt::arg("bufsize", bufsize_),
|
||||||
|
fmt::arg("samplerate", samplerate_), fmt::arg("latency", fmt::format("{:.2f}", latency)),
|
||||||
|
fmt::arg("xruns", xruns_)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call parent update
|
||||||
|
ALabel::update();
|
||||||
|
}
|
||||||
|
|
||||||
|
int JACK::bufSize(jack_nframes_t size) {
|
||||||
|
bufsize_ = size;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JACK::sampleRate(jack_nframes_t rate) {
|
||||||
|
samplerate_ = rate;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JACK::xrun() {
|
||||||
|
xruns_ += 1;
|
||||||
|
state_ = "xrun";
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JACK::shutdown() {
|
||||||
|
std::lock_guard<std::mutex> lock(mutex_);
|
||||||
|
running_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules
|
||||||
|
|
||||||
|
int bufSizeCallback(jack_nframes_t size, void *obj) {
|
||||||
|
return static_cast<waybar::modules::JACK *>(obj)->bufSize(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sampleRateCallback(jack_nframes_t rate, void *obj) {
|
||||||
|
return static_cast<waybar::modules::JACK *>(obj)->sampleRate(rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
int xrunCallback(void *obj) { return static_cast<waybar::modules::JACK *>(obj)->xrun(); }
|
||||||
|
|
||||||
|
void shutdownCallback(void *obj) { return static_cast<waybar::modules::JACK *>(obj)->shutdown(); }
|
Loading…
Reference in New Issue