feat: pulseaudio slider module
This commit is contained in:
parent
c9e129cda2
commit
442a4b0da0
|
@ -0,0 +1,19 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "AModule.hpp"
|
||||||
|
#include "gtkmm/scale.h"
|
||||||
|
|
||||||
|
namespace waybar {
|
||||||
|
|
||||||
|
class ASlider : public AModule {
|
||||||
|
public:
|
||||||
|
ASlider(const Json::Value& config, const std::string& name, const std::string& id);
|
||||||
|
virtual void onValueChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool vertical_ = false;
|
||||||
|
int min_ = 0, max_ = 100, curr_ = 50;
|
||||||
|
Gtk::Scale scale_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "ASlider.hpp"
|
||||||
|
#include "util/audio_backend.hpp"
|
||||||
|
namespace waybar::modules {
|
||||||
|
|
||||||
|
enum class PulseaudioSliderTarget {
|
||||||
|
Sink,
|
||||||
|
Source,
|
||||||
|
};
|
||||||
|
|
||||||
|
class PulseaudioSlider : public ASlider {
|
||||||
|
public:
|
||||||
|
PulseaudioSlider(const std::string&, const Json::Value&);
|
||||||
|
virtual ~PulseaudioSlider() = default;
|
||||||
|
|
||||||
|
void update() override;
|
||||||
|
void onValueChanged() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<util::AudioBackend> backend = nullptr;
|
||||||
|
PulseaudioSliderTarget target = PulseaudioSliderTarget::Sink;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace waybar::modules
|
|
@ -66,7 +66,7 @@ class AudioBackend {
|
||||||
AudioBackend(std::function<void()> on_updated_cb, private_constructor_tag tag);
|
AudioBackend(std::function<void()> on_updated_cb, private_constructor_tag tag);
|
||||||
~AudioBackend();
|
~AudioBackend();
|
||||||
|
|
||||||
void changeVolume(uint16_t volume, uint16_t max_volume = 100);
|
void changeVolume(uint16_t volume, uint16_t min_volume = 0, uint16_t max_volume = 100);
|
||||||
void changeVolume(ChangeType change_type, double step = 1, uint16_t max_volume = 100);
|
void changeVolume(ChangeType change_type, double step = 1, uint16_t max_volume = 100);
|
||||||
|
|
||||||
void setIgnoredSinks(const Json::Value& config);
|
void setIgnoredSinks(const Json::Value& config);
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
waybar-pulseaudio-slider(5)
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
waybar - pulseaudio slider module
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
The *pulseaudio slider* module displays and controls the current volume of the default sink or source as a bar.
|
||||||
|
|
||||||
|
The volume can be controlled by dragging the slider accross the bar, or clicking on a specific position.
|
||||||
|
|
||||||
|
# CONFIGURATION
|
||||||
|
|
||||||
|
*min*: ++
|
||||||
|
typeof: int ++
|
||||||
|
default: 0 ++
|
||||||
|
The minimum volume value the slider should display and set.
|
||||||
|
|
||||||
|
*max*: ++
|
||||||
|
typeof: int ++
|
||||||
|
default: 100 ++
|
||||||
|
The maximum volume value the slider should display and set.
|
||||||
|
|
||||||
|
*orientation*: ++
|
||||||
|
typeof: string ++
|
||||||
|
default: horizontal ++
|
||||||
|
The orientation of the slider. Can be either `horizontal` or `vertical`.
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
```
|
||||||
|
"modules-right": [
|
||||||
|
"pulseaudio-slider",
|
||||||
|
],
|
||||||
|
"pulseaudio/slider": {
|
||||||
|
"min": 0,
|
||||||
|
"max": 100,
|
||||||
|
"orientation": "horizontal"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# STYLE
|
||||||
|
|
||||||
|
The slider is a component with multiple CSS Nodes, of which the following are exposed:
|
||||||
|
|
||||||
|
*#pulseaudio-slider*: ++
|
||||||
|
Controls the style of the box *around* the slider and bar.
|
||||||
|
|
||||||
|
*#pulseaudio-slider slider*: ++
|
||||||
|
Controls the style of the slider handle.
|
||||||
|
|
||||||
|
*#pulseaudio-slider trough*: ++
|
||||||
|
Controls the style of the part of the bar that has not been filled.
|
||||||
|
|
||||||
|
*#pulseaudio-slider highlight*: ++
|
||||||
|
Controls the style of the part of the bar that has been filled.
|
||||||
|
|
||||||
|
## STYLE EXAMPLE
|
||||||
|
|
||||||
|
```
|
||||||
|
#pulseaudio-slider slider {
|
||||||
|
min-height: 0px;
|
||||||
|
min-width: 0px;
|
||||||
|
opacity: 0;
|
||||||
|
background-image: none;
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pulseaudio-slider trough {
|
||||||
|
min-height: 80px;
|
||||||
|
min-width: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pulseaudio-slider highlight {
|
||||||
|
min-width: 10px;
|
||||||
|
border-radius: 5px;
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
```
|
|
@ -166,6 +166,7 @@ src_files = files(
|
||||||
'src/modules/image.cpp',
|
'src/modules/image.cpp',
|
||||||
'src/modules/temperature.cpp',
|
'src/modules/temperature.cpp',
|
||||||
'src/modules/user.cpp',
|
'src/modules/user.cpp',
|
||||||
|
'src/ASlider.cpp',
|
||||||
'src/main.cpp',
|
'src/main.cpp',
|
||||||
'src/bar.cpp',
|
'src/bar.cpp',
|
||||||
'src/client.cpp',
|
'src/client.cpp',
|
||||||
|
@ -274,6 +275,7 @@ endif
|
||||||
if libpulse.found()
|
if libpulse.found()
|
||||||
add_project_arguments('-DHAVE_LIBPULSE', language: 'cpp')
|
add_project_arguments('-DHAVE_LIBPULSE', language: 'cpp')
|
||||||
src_files += 'src/modules/pulseaudio.cpp'
|
src_files += 'src/modules/pulseaudio.cpp'
|
||||||
|
src_files += 'src/modules/pulseaudio_slider.cpp'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if libjack.found()
|
if libjack.found()
|
||||||
|
@ -441,6 +443,7 @@ if scdoc.found()
|
||||||
'waybar-mpris.5.scd',
|
'waybar-mpris.5.scd',
|
||||||
'waybar-network.5.scd',
|
'waybar-network.5.scd',
|
||||||
'waybar-pulseaudio.5.scd',
|
'waybar-pulseaudio.5.scd',
|
||||||
|
'waybar-pulseaudio-slider.5.scd',
|
||||||
'waybar-river-mode.5.scd',
|
'waybar-river-mode.5.scd',
|
||||||
'waybar-river-tags.5.scd',
|
'waybar-river-tags.5.scd',
|
||||||
'waybar-river-window.5.scd',
|
'waybar-river-window.5.scd',
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
#include "ASlider.hpp"
|
||||||
|
|
||||||
|
#include "gtkmm/adjustment.h"
|
||||||
|
#include "gtkmm/enums.h"
|
||||||
|
|
||||||
|
namespace waybar {
|
||||||
|
|
||||||
|
ASlider::ASlider(const Json::Value& config, const std::string& name, const std::string& id)
|
||||||
|
: AModule(config, name, id, false, false),
|
||||||
|
vertical_(config_["orientation"].asString() == "vertical"),
|
||||||
|
scale_(vertical_ ? Gtk::ORIENTATION_VERTICAL : Gtk::ORIENTATION_HORIZONTAL) {
|
||||||
|
scale_.set_name(name);
|
||||||
|
if (!id.empty()) {
|
||||||
|
scale_.get_style_context()->add_class(id);
|
||||||
|
}
|
||||||
|
event_box_.add(scale_);
|
||||||
|
scale_.signal_value_changed().connect(sigc::mem_fun(*this, &ASlider::onValueChanged));
|
||||||
|
|
||||||
|
if (config_["min"].isUInt()) {
|
||||||
|
min_ = config_["min"].asUInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config_["max"].isUInt()) {
|
||||||
|
max_ = config_["max"].asUInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
scale_.set_inverted(vertical_);
|
||||||
|
scale_.set_draw_value(false);
|
||||||
|
scale_.set_adjustment(Gtk::Adjustment::create(curr_, min_, max_ + 1, 1, 1, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ASlider::onValueChanged() {}
|
||||||
|
|
||||||
|
} // namespace waybar
|
|
@ -1,5 +1,9 @@
|
||||||
#include "factory.hpp"
|
#include "factory.hpp"
|
||||||
|
|
||||||
|
#ifdef HAVE_LIBPULSE
|
||||||
|
#include "modules/pulseaudio_slider.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
waybar::Factory::Factory(const Bar& bar, const Json::Value& config) : bar_(bar), config_(config) {}
|
waybar::Factory::Factory(const Bar& bar, const Json::Value& config) : bar_(bar), config_(config) {}
|
||||||
|
|
||||||
waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
||||||
|
@ -136,6 +140,9 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const {
|
||||||
if (ref == "pulseaudio") {
|
if (ref == "pulseaudio") {
|
||||||
return new waybar::modules::Pulseaudio(id, config_[name]);
|
return new waybar::modules::Pulseaudio(id, config_[name]);
|
||||||
}
|
}
|
||||||
|
if (ref == "pulseaudio/slider") {
|
||||||
|
return new waybar::modules::PulseaudioSlider(id, config_[name]);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_LIBMPDCLIENT
|
#ifdef HAVE_LIBMPDCLIENT
|
||||||
if (ref == "mpd") {
|
if (ref == "mpd") {
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
#include "modules/pulseaudio_slider.hpp"
|
||||||
|
|
||||||
|
namespace waybar::modules {
|
||||||
|
|
||||||
|
PulseaudioSlider::PulseaudioSlider(const std::string& id, const Json::Value& config)
|
||||||
|
: ASlider(config, "pulseaudio-slider", id) {
|
||||||
|
backend = util::AudioBackend::getInstance([this] { this->dp.emit(); });
|
||||||
|
backend->setIgnoredSinks(config_["ignored-sinks"]);
|
||||||
|
|
||||||
|
if (config_["target"].isString()) {
|
||||||
|
std::string target = config_["target"].asString();
|
||||||
|
if (target == "sink") {
|
||||||
|
this->target = PulseaudioSliderTarget::Sink;
|
||||||
|
} else if (target == "source") {
|
||||||
|
this->target = PulseaudioSliderTarget::Source;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PulseaudioSlider::update() {
|
||||||
|
switch (target) {
|
||||||
|
case PulseaudioSliderTarget::Sink:
|
||||||
|
if (backend->getSinkMuted()) {
|
||||||
|
scale_.set_value(min_);
|
||||||
|
} else {
|
||||||
|
scale_.set_value(backend->getSinkVolume());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PulseaudioSliderTarget::Source:
|
||||||
|
if (backend->getSourceMuted()) {
|
||||||
|
scale_.set_value(min_);
|
||||||
|
} else {
|
||||||
|
scale_.set_value(backend->getSourceVolume());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PulseaudioSlider::onValueChanged() {
|
||||||
|
uint16_t volume = scale_.get_value();
|
||||||
|
backend->changeVolume(volume, min_, max_);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace waybar::modules
|
|
@ -204,11 +204,12 @@ void AudioBackend::serverInfoCb(pa_context *context, const pa_server_info *i, vo
|
||||||
pa_context_get_source_info_list(context, sourceInfoCb, data);
|
pa_context_get_source_info_list(context, sourceInfoCb, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioBackend::changeVolume(uint16_t volume, uint16_t max_volume) {
|
void AudioBackend::changeVolume(uint16_t volume, uint16_t min_volume, uint16_t max_volume) {
|
||||||
double volume_tick = static_cast<double>(PA_VOLUME_NORM) / 100;
|
double volume_tick = static_cast<double>(PA_VOLUME_NORM) / 100;
|
||||||
pa_cvolume pa_volume = pa_volume_;
|
pa_cvolume pa_volume = pa_volume_;
|
||||||
|
|
||||||
volume = std::min(volume, max_volume);
|
volume = std::min(volume, max_volume);
|
||||||
|
volume = std::max(volume, min_volume);
|
||||||
pa_cvolume_set(&pa_volume, pa_volume_.channels, volume * volume_tick);
|
pa_cvolume_set(&pa_volume, pa_volume_.channels, volume * volume_tick);
|
||||||
|
|
||||||
pa_context_set_sink_volume_by_index(context_, sink_idx_, &pa_volume, volumeModifyCb, this);
|
pa_context_set_sink_volume_by_index(context_, sink_idx_, &pa_volume, volumeModifyCb, this);
|
||||||
|
|
Loading…
Reference in New Issue