Files
Waybar/include/modules/cava/cavaGLSL.hpp
T
Viktar Lukashonak 5c979152de refactor(cava): fix thread-safety, resource leaks, and style violations
Comprehensive refactor of the cava module backend and frontends.

Style & naming
- Rename Cava -> CavaRaw; snake_case methods -> lowerCamelCase
- Replace NULL with nullptr; replace C-style casts with static_cast
- Add explicit standard-library includes (<memory>, <string>, <chrono>)
- Fix missing trailing underscores on member variables

Architecture
- Remove Gtk::GLArea multiple inheritance in CavaGLSL (composition)
- Return std::unique_ptr from factory; add doAction() to GLSL variant
- Encapsulate thread timing arithmetic in AdaptiveDelay struct

Thread safety & correctness
- Replace raw sigc::signal with SafeSignal for cross-thread marshalling
- Fix data race between loadConfig() and out_thread_ (recursive_mutex)
- Fix audio_raw shallow-copy use-after-free via deep-copy AudioRaw payload
- Make loadConfig() exception-safe with CavaConfigGuard RAII
- Fix blocking read_thread_ race on shutdown (condition_variable + timeout join)
- Fix isSilent() data race (acquire pthread mutex)
- Eliminate doUpdate() recursion (iteration instead)
- Guard audio_raw_clean() against uninitialized state
- Fix format-icons underflow and cava_config buffer overflow
- Store config by value to prevent dangling references on reload
- Cache frontend config and refresh on runtime changes
- Fix signed-char icon lookup bug on x86
- Prevent Json::Value mutation bloat via const-ref lookups
- Broaden exception catches in worker threads (std::exception)

Resource management & GL robustness
- Fix OpenGL resource leaks (persist VBO/IBO/VAO; explicit destructor cleanup)
- Fix shader error handling crashes (valid infoLog allocation)
- Cache uniform locations instead of querying per frame
- Fix gradient color uninitialized stack memory (zero-init + clamped count)
- Fix shader time uniform integer division bug (float arithmetic)
- Add explicit VAO bind in onRender()
- Handle runtime surface config changes independently of shader changes
- Clamp negative gradient_count before GL upload

Follow-up
- Singleton API split (inst() + configure()) intentionally deferred to a
  dedicated PR because it changes the public constructor contract.
2026-07-13 19:50:09 +03:00

80 lines
2.0 KiB
C++

#pragma once
#include <epoxy/gl.h>
#include <gtkmm/glarea.h>
#include <map>
#include <string>
#include <array>
#include <sigc++/connection.h>
#include "AModule.hpp"
#include "cava_backend.hpp"
namespace waybar::modules::cava {
class CavaGLSL final : public AModule {
public:
CavaGLSL(const std::string&, const Json::Value&);
~CavaGLSL();
auto doAction(const std::string& name) -> void override;
private:
using Action = void (CavaGLSL::*)();
Gtk::GLArea gl_area_;
std::shared_ptr<CavaBackend> backend_;
// Cached config params (deep-copied strings to avoid dangling char* on backend reload)
int sdl_width_{0};
int sdl_height_{0};
int bar_width_{0};
int bar_spacing_{0};
int gradient_count_{0};
std::string vertex_shader_;
std::string fragment_shader_;
std::string bcolor_;
std::string color_;
std::array<std::string, 8> gradient_colors_;
int frame_counter_{0};
bool silence_{false};
bool hide_on_silence_{false};
bool mapped_{false};
// Cava method
void pauseResume();
auto onUpdate(const CavaBackend::AudioRaw& input) -> void;
auto onSilence() -> void;
auto onBackendConfigChanged() -> void;
void cacheConfigParams(const ::cava::config_params& src);
// Member variable to store audio data
CavaBackend::AudioRaw m_data_;
GLuint shaderProgram_{0};
// OpenGL variables
GLuint fbo_{0};
GLuint texture_{0};
GLuint vbo_{0};
GLuint ibo_{0};
GLuint vao_{0};
GLint uniform_bars_;
GLint uniform_previous_bars_;
GLint uniform_bars_count_;
GLint uniform_time_;
GLint uniform_input_texture_;
// Methods
void onRealize();
bool onRender(const Glib::RefPtr<Gdk::GLContext>& context);
void initShaders();
void initSurface();
void initGLSL();
GLuint loadShader(const std::string& fileName, GLenum type);
void cleanupGL();
// ModuleActionMap
static const std::map<std::string, Action> actionMap_;
sigc::connection audio_raw_update_conn_;
sigc::connection silence_conn_;
sigc::connection config_changed_conn_;
};
} // namespace waybar::modules::cava