Merge remote-tracking branch 'origin/master' into feature-clock-calendar-css-classes
This commit is contained in:
@@ -41,6 +41,9 @@ auto waybar::modules::Cpu::update() -> void {
|
||||
auto icons = std::vector<std::string>{state};
|
||||
fmt::dynamic_format_arg_store<fmt::format_context> store;
|
||||
store.push_back(fmt::arg("load", load1));
|
||||
store.push_back(fmt::arg("load1", load1));
|
||||
store.push_back(fmt::arg("load5", load5));
|
||||
store.push_back(fmt::arg("load15", load15));
|
||||
store.push_back(fmt::arg("usage", total_usage));
|
||||
store.push_back(fmt::arg("icon", getIcon(total_usage, icons)));
|
||||
store.push_back(fmt::arg("max_frequency", max_frequency));
|
||||
|
||||
@@ -10,73 +10,51 @@ PulseaudioSlider::PulseaudioSlider(const std::string& id, const Json::Value& con
|
||||
if (config_["target"].isString()) {
|
||||
std::string target = config_["target"].asString();
|
||||
if (target == "sink") {
|
||||
this->target = PulseaudioSliderTarget::Sink;
|
||||
this->target = util::PulseaudioTarget::Sink;
|
||||
} else if (target == "source") {
|
||||
this->target = PulseaudioSliderTarget::Source;
|
||||
this->target = util::PulseaudioTarget::Source;
|
||||
}
|
||||
}
|
||||
|
||||
if (config_["zero-on-mute"].isBool()) {
|
||||
zero_on_mute = config_["zero-on-mute"].asBool();
|
||||
}
|
||||
|
||||
if (config_["unmute-on-volume-change"].isBool()) {
|
||||
unmute_on_volume_change = config_["unmute-on-volume-change"].asBool();
|
||||
}
|
||||
}
|
||||
|
||||
void PulseaudioSlider::update() {
|
||||
switch (target) {
|
||||
case PulseaudioSliderTarget::Sink:
|
||||
if (backend->getSinkMuted()) {
|
||||
scale_.set_value(min_);
|
||||
} else {
|
||||
scale_.set_value(backend->getSinkVolume());
|
||||
}
|
||||
break;
|
||||
uint16_t display_value = backend->getVolume(target);
|
||||
bool is_muted = backend->getMuted(target);
|
||||
|
||||
case PulseaudioSliderTarget::Source:
|
||||
if (backend->getSourceMuted()) {
|
||||
scale_.set_value(min_);
|
||||
} else {
|
||||
scale_.set_value(backend->getSourceVolume());
|
||||
}
|
||||
break;
|
||||
if (is_muted) {
|
||||
if (zero_on_mute) {
|
||||
display_value = min_;
|
||||
}
|
||||
if (!previously_muted) {
|
||||
scale_.get_style_context()->add_class("muted");
|
||||
}
|
||||
} else if (previously_muted) {
|
||||
scale_.get_style_context()->remove_class("muted");
|
||||
}
|
||||
|
||||
scale_.set_value(display_value);
|
||||
|
||||
previously_muted = is_muted;
|
||||
}
|
||||
|
||||
void PulseaudioSlider::onValueChanged() {
|
||||
bool is_mute = false;
|
||||
uint16_t slider_value = scale_.get_value();
|
||||
|
||||
switch (target) {
|
||||
case PulseaudioSliderTarget::Sink:
|
||||
if (backend->getSinkMuted()) {
|
||||
is_mute = true;
|
||||
}
|
||||
break;
|
||||
|
||||
case PulseaudioSliderTarget::Source:
|
||||
if (backend->getSourceMuted()) {
|
||||
is_mute = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t volume = scale_.get_value();
|
||||
|
||||
if (is_mute) {
|
||||
// Avoid setting sink/source to volume 0 if the user muted if via another mean.
|
||||
if (volume == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the sink/source is mute, but the user clicked the slider, unmute it!
|
||||
else {
|
||||
switch (target) {
|
||||
case PulseaudioSliderTarget::Sink:
|
||||
backend->toggleSinkMute(false);
|
||||
break;
|
||||
|
||||
case PulseaudioSliderTarget::Source:
|
||||
backend->toggleSourceMute(false);
|
||||
break;
|
||||
}
|
||||
// Avoid setting sink/source to volume 0 if the user muted it via other means.
|
||||
if (!backend->getMuted(target) || slider_value != 0) {
|
||||
if (unmute_on_volume_change) {
|
||||
backend->unmute(target);
|
||||
}
|
||||
backend->changeVolume(slider_value, min_, max_);
|
||||
}
|
||||
|
||||
backend->changeVolume(volume, min_, max_);
|
||||
}
|
||||
|
||||
} // namespace waybar::modules
|
||||
} // namespace waybar::modules
|
||||
|
||||
@@ -20,6 +20,24 @@ waybar::modules::Temperature::Temperature(const std::string& id, const Json::Val
|
||||
if (check_set_path(item.asString())) break;
|
||||
};
|
||||
|
||||
auto find_hwmon_by_name = [](const std::string& name) -> std::optional<std::filesystem::path> {
|
||||
for (const auto& entry : std::filesystem::directory_iterator("/sys/class/hwmon")) {
|
||||
std::ifstream f(entry.path() / "name");
|
||||
std::string hwname;
|
||||
if (f >> hwname && hwname == name) {
|
||||
return entry.path();
|
||||
}
|
||||
}
|
||||
return std::nullopt;
|
||||
};
|
||||
|
||||
// ensure either hwmon-name OR old paths are used, not both
|
||||
if (config_["hwmon-name"].isString() &&
|
||||
(!config_["hwmon-path"].isNull() || !config_["hwmon-path-abs"].isNull())) {
|
||||
throw std::runtime_error(
|
||||
"hwmon-name cannot be used together with hwmon-path or hwmon-path-abs");
|
||||
}
|
||||
|
||||
// if hwmon_path is an array, loop to find first valid item
|
||||
traverseAsArray(config_["hwmon-path"], [this](const std::string& path) {
|
||||
if (!std::filesystem::exists(path)) return false;
|
||||
@@ -40,6 +58,20 @@ waybar::modules::Temperature::Temperature(const std::string& id, const Json::Val
|
||||
});
|
||||
}
|
||||
|
||||
if (file_path_.empty() && config_["hwmon-name"].isString()) {
|
||||
if (!config_["input-filename"].isString()) {
|
||||
throw std::runtime_error("hwmon-name requires input-filename to be set");
|
||||
}
|
||||
|
||||
auto hwmon = find_hwmon_by_name(config_["hwmon-name"].asString());
|
||||
|
||||
if (!hwmon) {
|
||||
throw std::runtime_error("hwmon-name '" + config_["hwmon-name"].asString() + "' not found");
|
||||
}
|
||||
|
||||
file_path_ = hwmon->string() + "/" + config_["input-filename"].asString();
|
||||
}
|
||||
|
||||
if (file_path_.empty()) {
|
||||
auto zone = config_["thermal-zone"].isInt() ? config_["thermal-zone"].asInt() : 0;
|
||||
file_path_ = fmt::format("/sys/class/thermal/thermal_zone{}/temp", zone);
|
||||
|
||||
@@ -261,6 +261,14 @@ void AudioBackend::serverInfoCb(pa_context* context, const pa_server_info* i, vo
|
||||
pa_context_get_source_info_list(context, sourceInfoCb, data);
|
||||
}
|
||||
|
||||
uint16_t AudioBackend::getVolume(PulseaudioTarget target) const {
|
||||
if (target == PulseaudioTarget::Source) {
|
||||
return source_volume_;
|
||||
} else {
|
||||
return volume_;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioBackend::changeVolume(uint16_t volume, uint16_t min_volume, uint16_t max_volume) {
|
||||
// Early return if context is not ready
|
||||
if ((context_ == nullptr) || pa_context_get_state(context_) != PA_CONTEXT_READY) {
|
||||
@@ -370,6 +378,14 @@ void AudioBackend::changeVolume(ChangeType change_type, double step, uint16_t ma
|
||||
pa_threaded_mainloop_unlock(mainloop_);
|
||||
}
|
||||
|
||||
bool AudioBackend::getMuted(PulseaudioTarget target) const {
|
||||
if (target == PulseaudioTarget::Source) {
|
||||
return source_muted_;
|
||||
} else {
|
||||
return muted_;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioBackend::toggleSinkMute() {
|
||||
if (context_ == nullptr || pa_context_get_state(context_) != PA_CONTEXT_READY) return;
|
||||
muted_ = !muted_;
|
||||
@@ -406,6 +422,14 @@ void AudioBackend::toggleSourceMute(bool mute) {
|
||||
pa_threaded_mainloop_unlock(mainloop_);
|
||||
}
|
||||
|
||||
void AudioBackend::unmute(PulseaudioTarget target) {
|
||||
if (target == PulseaudioTarget::Source) {
|
||||
toggleSourceMute(false);
|
||||
} else {
|
||||
toggleSinkMute(false);
|
||||
}
|
||||
}
|
||||
|
||||
bool AudioBackend::isBluetooth() {
|
||||
return monitor_.find("a2dp_sink") != std::string::npos || // PulseAudio
|
||||
monitor_.find("a2dp-sink") != std::string::npos || // PipeWire
|
||||
|
||||
Reference in New Issue
Block a user