From a650c7d90c40163db0ab67beb3141c09a9750a66 Mon Sep 17 00:00:00 2001 From: Jake Stanger Date: Sun, 16 Jan 2022 23:55:13 +0000 Subject: [PATCH] feat: image module Module which renders an image onto the bar. --- include/factory.hpp | 1 + include/modules/image.hpp | 34 ++++++++++++++++++ man/waybar-image.5.scd | 72 +++++++++++++++++++++++++++++++++++++++ meson.build | 1 + src/factory.cpp | 2 ++ src/modules/image.cpp | 59 ++++++++++++++++++++++++++++++++ 6 files changed, 169 insertions(+) create mode 100644 include/modules/image.hpp create mode 100644 man/waybar-image.5.scd create mode 100644 src/modules/image.cpp diff --git a/include/factory.hpp b/include/factory.hpp index 3855ce22..421689b3 100644 --- a/include/factory.hpp +++ b/include/factory.hpp @@ -56,6 +56,7 @@ #endif #include "bar.hpp" #include "modules/custom.hpp" +#include "modules/image.hpp" #include "modules/temperature.hpp" #if defined(__linux__) # ifdef WANT_RFKILL diff --git a/include/modules/image.hpp b/include/modules/image.hpp new file mode 100644 index 00000000..00b8393c --- /dev/null +++ b/include/modules/image.hpp @@ -0,0 +1,34 @@ +#pragma once + +#include +#include + +#include +#include + +#include "ALabel.hpp" +#include "util/command.hpp" +#include "util/json.hpp" +#include "util/sleeper_thread.hpp" + +namespace waybar::modules { + +class Image : public AModule { + public: + Image(const std::string&, const std::string&, const Json::Value&); + auto update() -> void; + void refresh(int /*signal*/); + + private: + void delayWorker(); + void handleEvent(); + + Gtk::Image image_; + std::string path_; + int size_; + int interval_; + + util::SleeperThread thread_; +}; + +} // namespace waybar::modules diff --git a/man/waybar-image.5.scd b/man/waybar-image.5.scd new file mode 100644 index 00000000..feff9f6e --- /dev/null +++ b/man/waybar-image.5.scd @@ -0,0 +1,72 @@ +waybar-custom(5) + +# NAME + +waybar - image module + +# DESCRIPTION + +The *image* module displays an image from a path. + +# CONFIGURATION + +Addressed by *custom/* + +*path*: ++ + typeof: string ++ + The path to the image. + +*size*: ++ + typeof: integer ++ + The width/height to render the image. + +*interval*: ++ + typeof: integer ++ + The interval (in seconds) to re-render the image. + This is useful if the contents of *path* changes. + If no *interval* is defined, the image will only be rendered once. + +*signal*: ++ + typeof: integer ++ + The signal number used to update the module. + This can be used instead of *interval* if the file changes irregularly. + The number is valid between 1 and N, where *SIGRTMIN+N* = *SIGRTMAX*. + +*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-update*: ++ + typeof: string ++ + Command to execute when the module is updated. + +*on-scroll-up*: ++ + typeof: string ++ + Command to execute when scrolling up on the module. + +*on-scroll-down*: ++ + typeof: string ++ + Command to execute when scrolling down on the module. + +*smooth-scrolling-threshold*: ++ + typeof: double ++ + Threshold to be used when scrolling. + +# EXAMPLES + +## Spotify: + +## mpd: + +``` +"image/album-art": { + "path": "/tmp/mpd_art", + "size": 32, + "interval": 5, + "on-click": "mpc toggle" +} +``` \ No newline at end of file diff --git a/meson.build b/meson.build index 2c644cc3..56eb4749 100644 --- a/meson.build +++ b/meson.build @@ -145,6 +145,7 @@ src_files = files( 'src/modules/custom.cpp', 'src/modules/disk.cpp', 'src/modules/idle_inhibitor.cpp', + 'src/modules/image.cpp', 'src/modules/temperature.cpp', 'src/main.cpp', 'src/bar.cpp', diff --git a/src/factory.cpp b/src/factory.cpp index 900653b5..72c10c74 100644 --- a/src/factory.cpp +++ b/src/factory.cpp @@ -112,6 +112,8 @@ waybar::AModule* waybar::Factory::makeModule(const std::string& name) const { #endif if (ref.compare(0, 7, "custom/") == 0 && ref.size() > 7) { return new waybar::modules::Custom(ref.substr(7), id, config_[name]); + } else if (ref.compare(0, 6, "image/") == 0 && ref.size() > 6) { + return new waybar::modules::Image(ref.substr(6), id, config_[name]); } } catch (const std::exception& e) { auto err = fmt::format("Disabling module \"{}\", {}", name, e.what()); diff --git a/src/modules/image.cpp b/src/modules/image.cpp new file mode 100644 index 00000000..eed19aea --- /dev/null +++ b/src/modules/image.cpp @@ -0,0 +1,59 @@ +#include "modules/image.hpp" + +#include + +waybar::modules::Image::Image(const std::string& name, const std::string& id, + const Json::Value& config) + : AModule(config, "image-" + name, id, "{}") { + event_box_.add(image_); + + dp.emit(); + + path_ = config["path"].asString(); + size_ = config["size"].asInt(); + + interval_ = config_["interval"].asInt(); + + if (size_ == 0) { + size_ = 16; + } + + if (interval_ == 0) { + interval_ = INT_MAX; + } + + delayWorker(); +} + +void waybar::modules::Image::delayWorker() { + thread_ = [this] { + dp.emit(); + auto interval = std::chrono::seconds(interval_); + thread_.sleep_for(interval); + }; +} + +void waybar::modules::Image::refresh(int sig) { + if (sig == SIGRTMIN + config_["signal"].asInt()) { + thread_.wake_up(); + } +} + +auto waybar::modules::Image::update() -> void { + Glib::RefPtr pixbuf; + + if (Glib::file_test(path_, Glib::FILE_TEST_EXISTS)) + pixbuf = Gdk::Pixbuf::create_from_file(path_, size_, size_); + else + pixbuf = {}; + + if (pixbuf) { + image_.set(pixbuf); + image_.show(); + } else { + image_.clear(); + image_.hide(); + } + + AModule::update(); +}