From c368696cc2840a2ea4f71bf1bc09fd2ea1e220a2fae30c2e2eb4ff9f5735387c Mon Sep 17 00:00:00 2001 From: ADAM David Alan Martin Date: Mon, 26 Jan 2026 03:47:52 -0500 Subject: [PATCH] I dunno that this makes it any easier... I tried splitting up the sources to speed up some compiling... but it didn't help. I dunno that it's more readable this way. I'm checkpointing this just in case. --- ConfigFile.cc | 84 ++++++++++++++++++++++++++++++++++++++++ ConfigFile.h | 73 +---------------------------------- Makefile | 7 +++- MouseWheelSlider.cc | 44 +++++++++++++++++++++ MouseWheelSlider.h | 13 +++++++ backlight.cc | 65 +++++++++++++++++++++++++++++++ backlight.h | 8 ++++ power_console_common.h | 51 +----------------------- power_console_main.cc | 88 +++++------------------------------------- power_profile.cc | 38 ++++++++++++++++++ power_profile.h | 8 ++++ 11 files changed, 279 insertions(+), 200 deletions(-) create mode 100644 ConfigFile.cc create mode 100644 MouseWheelSlider.cc create mode 100644 MouseWheelSlider.h create mode 100644 backlight.cc create mode 100644 backlight.h create mode 100644 power_profile.cc create mode 100644 power_profile.h diff --git a/ConfigFile.cc b/ConfigFile.cc new file mode 100644 index 0000000..5d561f4 --- /dev/null +++ b/ConfigFile.cc @@ -0,0 +1,84 @@ +#include "ConfigFile.h" + +#include +#include + +namespace Config::Hydrogen ::detail:: ConfigFile_m +{ + namespace + { + struct EoF {}; + + std::string + readLine( std::istream &input ) + { + std::string rv; + std::getline( input, rv ); + if( not input ) throw EoF{}; + + // SStrip trailing '#' comments... + const auto endComment= std::find( begin( rv ), end( rv ), '#' ); + rv.erase( endComment, end( rv ) ); + return rv; + } + + std::string + trimWhitespace( std::string s ) + { + // Trim from the front + std::reverse( begin( s ), end( s ) ); + while( not s.empty() and s.back() == ' ' ) s.pop_back(); + + // Trim from the back + std::reverse( begin( s ), end( s ) ); + while( not s.empty() and s.back() == ' ' ) s.pop_back(); + + return s; + } + + auto + parseLine( const std::string &line ) + { + const auto split= std::find( begin( line ), end( line ), '=' ); + if( split == end( line ) ) throw std::runtime_error{ "Unable to parse configuration line: `" + line + "`" }; + const auto key= trimWhitespace( { begin( line ), split } ); + const auto value= trimWhitespace( { split + 1, end( line ) } ); + + return std::tuple{ key, value }; + } + } + + ConfigFile::ConfigFile( std::istream &&input, const std::map< std::string, std::string > &schema ) + : config( schema ) + { + while( input ) + try + { + const std::string line= trimWhitespace( readLine( input ) ); + if( line.empty() ) continue; // Skip blank lines. + + const auto [ key, value ]= parseLine( line ); + + if( not schema.contains( key ) ) + { + std::cerr << "Unrecognized key in config file: `" << key << "`" << std::endl; + continue; + } + + config.at( key )= value; + } + catch( const EoF & ) { break; } + + std::cerr << "Configuration parsed:" << std::endl; + for( const auto &[ key, value ]: config ) + { + std::cerr << key << " = " << value << std::endl; + } + } + + std::string + ConfigFile::get( const std::string &name ) const + { + return config.at( name ); + } +} diff --git a/ConfigFile.h b/ConfigFile.h index 3b3a7b2..b861b31 100644 --- a/ConfigFile.h +++ b/ConfigFile.h @@ -3,8 +3,6 @@ #include #include #include -#include -#include namespace Config::inline Hydrogen {} @@ -20,77 +18,10 @@ namespace Config::Hydrogen ::detail:: ConfigFile_m private: std::map< std::string, std::string > config; - struct EoF {}; - - std::string - readLine( std::istream &input ) - { - std::string rv; - std::getline( input, rv ); - if( not input ) throw EoF{}; - - // SStrip trailing '#' comments... - const auto endComment= std::find( begin( rv ), end( rv ), '#' ); - rv.erase( endComment, end( rv ) ); - return rv; - } - - std::string - trimWhitespace( std::string s ) - { - // Trim from the front - std::reverse( begin( s ), end( s ) ); - while( not s.empty() and s.back() == ' ' ) s.pop_back(); - - // Trim from the back - std::reverse( begin( s ), end( s ) ); - while( not s.empty() and s.back() == ' ' ) s.pop_back(); - - return s; - } - - auto - parseLine( const std::string &line ) - { - const auto split= std::find( begin( line ), end( line ), '=' ); - if( split == end( line ) ) throw std::runtime_error{ "Unable to parse configuration line: `" + line + "`" }; - const auto key= trimWhitespace( { begin( line ), split } ); - const auto value= trimWhitespace( { split + 1, end( line ) } ); - - return std::tuple{ key, value }; - } - public: - explicit - ConfigFile( std::istream &&input, const std::map< std::string, std::string > &schema ) - { - config= schema; - while( input ) - try - { - const std::string line= trimWhitespace( readLine( input ) ); - if( line.empty() ) continue; // Skip blank lines. - - const auto [ key, value ]= parseLine( line ); + explicit ConfigFile( std::istream &&input, const std::map< std::string, std::string > &schema ); - if( not schema.contains( key ) ) - { - std::cerr << "Unrecognized key in config file: `" << key << "`" << std::endl; - continue; - } - - config.at( key )= value; - } - catch( const EoF & ) { break; } - - std::cerr << "Configuration parsed:" << std::endl; - for( const auto &[ key, value ]: config ) - { - std::cerr << key << " = " << value << std::endl; - } - } - - std::string get( const std::string &name ) const { return config.at( name ); } + std::string get( const std::string &name ) const; }; } diff --git a/Makefile b/Makefile index f0315d7..2c77a70 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,7 @@ -OBJECTS := power_console.o power_console_main.o +OBJECTS= power_console.o power_console_main.o +OBJECTS+= MouseWheelSlider.o ConfigFile.o power_profile.o +OBJECTS+= backlight.o + X_INSTALL_DIR := /usr/X11R6 LINKOPTS := -L$(X_INSTALL_DIR)/lib -lfltk -lXext -lX11 -lm FLUID := fluid @@ -26,5 +29,7 @@ power_console_main.o: power_console_main.cc power_console.h power_console.h power_console.h: power_console.fluid $(FLUID) -c power_console.fluid +power_console.cxx: power_console.h + power_console.o: power_console.h power_console.cxx $(CXX) $(CXXFLAGS) -c power_console.cxx diff --git a/MouseWheelSlider.cc b/MouseWheelSlider.cc new file mode 100644 index 0000000..2c872be --- /dev/null +++ b/MouseWheelSlider.cc @@ -0,0 +1,44 @@ +#include "MouseWheelSlider.h" + +#include + + +MouseWheelSlider::MouseWheelSlider( const int x, const int y, const int w, const int h, + const char *const l ) + : Fl_Value_Slider( x, y, w, h, l ) +{ + + step( 1 ); +} + +int +MouseWheelSlider::handle( const int event ) +{ + switch( event ) + { + case FL_MOUSEWHEEL: + { + // Negative, because I use this for the Brightness control. + const int dy= -Fl::event_dy(); + + const int newVal= value() - dy * step(); + if( 0 ) std::cerr << "newVal: " << newVal << " max: " << maximum() << " min: " << minimum() << std::endl; + if( newVal >= maximum() + and newVal <= minimum() ) + { + value( newVal ); + } + + do_callback(); + + return 1; + } + break; + + default: + { + return this->Fl_Value_Slider::handle( event ); + } + break; + } +} diff --git a/MouseWheelSlider.h b/MouseWheelSlider.h new file mode 100644 index 0000000..5f103aa --- /dev/null +++ b/MouseWheelSlider.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include +#include + +class MouseWheelSlider : public Fl_Value_Slider +{ + public: + explicit MouseWheelSlider( const int x, const int y, const int w, const int h, const char *const l= 0 ); + + int handle( const int event ) override; +}; diff --git a/backlight.cc b/backlight.cc new file mode 100644 index 0000000..cdddab1 --- /dev/null +++ b/backlight.cc @@ -0,0 +1,65 @@ +#include "backlight.h" + +#include +#include +#include + +#include "power_console.h" + +int +getBacklightPercent( const std::filesystem::path &backlightPath ) +{ + std::ifstream i_max{ backlightPath / "max_brightness" }; + + int max; + i_max >> max; + + + std::ifstream inf{ backlightPath / "brightness" }; + int in; + inf >> in; + + return 100 * in / max; +} + +std::filesystem::path getBacklightPath(); + + +namespace +{ + void + changeBrightness( int pct ) + { + std::ifstream i_max{ getBacklightPath() / "max_brightness" }; + + int max; + i_max >> max; + + // Clamp to never hit 0 backlight or pass max. + int adj= std::clamp( max * pct / 100, 1, max ); + std::cerr << "Adjustment computed: " << adj << std::endl; + + std::ofstream out{ getBacklightPath() / "brightness" }; + out << adj; + } + + void + increaseBrightness( int pct ) + { + changeBrightness( pct ); + } + + void + decreaseBrightness( int pct ) + { + changeBrightness( -pct ); + } +} + +void +adjustBrightness( MouseWheelSlider *, void * ) +{ + const int amount= brightness->value(); + std::cerr << "Adjusting brightness by " << amount << std::endl; + changeBrightness( amount ); +} diff --git a/backlight.h b/backlight.h new file mode 100644 index 0000000..566aa4d --- /dev/null +++ b/backlight.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include "MouseWheelSlider.h" + +void adjustBrightness( MouseWheelSlider *, void * ); + +int getBacklightPercent( const std::filesystem::path &backlightPath ); diff --git a/power_console_common.h b/power_console_common.h index c4dcdce..8e35f04 100644 --- a/power_console_common.h +++ b/power_console_common.h @@ -1,56 +1,7 @@ #pragma once -#include -#include -#include - -#include +#include "MouseWheelSlider.h" void saverChosen(); void perfChosen(); void balChosen(); - -class MouseWheelSlider : public Fl_Value_Slider -{ - public: - explicit - MouseWheelSlider( const int x, const int y, const int w, const int h, - const char *const l= 0 ) - : Fl_Value_Slider( x, y, w, h, l ) - { - - step( 1 ); - } - - int - handle( const int event ) override - { - switch( event ) - { - case FL_MOUSEWHEEL: - { - // Negative, because I use this for the Brightness control. - const int dy= -Fl::event_dy(); - - const int newVal= value() - dy * step(); - if( 0 ) std::cerr << "newVal: " << newVal << " max: " << maximum() << " min: " << minimum() << std::endl; - if( newVal >= maximum() - and newVal <= minimum() ) - { - value( newVal ); - } - - do_callback(); - - return 1; - } - break; - - default: - { - return this->Fl_Value_Slider::handle( event ); - } - break; - } - } -}; diff --git a/power_console_main.cc b/power_console_main.cc index 25f0cfc..19e15cb 100644 --- a/power_console_main.cc +++ b/power_console_main.cc @@ -12,6 +12,8 @@ #include #include "ConfigFile.h" +#include "power_profile.h" +#include "backlight.h" namespace C { @@ -43,17 +45,16 @@ const std::map< int, Fl_Color > levelColors= { 100, FL_BLUE }, }; -const std::map< std::string, Fl_Round_Button ** > powerMode= -{ - { "power-saver", &saver }, - { "balanced", &balance }, - { "performance", &perfButton }, -}; - using Config::exports::ConfigFile; std::unique_ptr< ConfigFile > config; +std::filesystem::path +getBacklightPath() +{ + return config->get( "backlight_path" ); +} + std::string battLevelString= "UNKNOWN"; void @@ -92,31 +93,9 @@ scheduledUpdate( void * ) if( C::debugUpdate ) std::cerr << "AC state read as: " << ac << std::endl; - std::ifstream i_max{ C::path / config->get( "backlight_path" ) / "max_brightness" }; + const auto backlightPercent= getBacklightPercent( config->get( "backlight_path" ) ); - int max; - i_max >> max; - - - std::ifstream inf{ C::path / config->get( "backlight_path" ) / "brightness" }; - int in; - inf >> in; - - brightness->value( 100 * in / max ); -} - -// Since this requires launching bg processes, we only do it at startup and then every 30s. -void -profileUpdate( void * ) -{ - FILE *prof= popen( "powerprofilesctl get", "r" ); - char buffer[ 1024 ]= ""; - fscanf( prof, "%s", buffer ); - pclose( prof ); - - ( *powerMode.at( buffer ) )->setonly(); - - Fl::repeat_timeout( 30, profileUpdate, nullptr ); + brightness->value( backlightPercent ); } int @@ -175,14 +154,6 @@ consClicked( Fl_Light_Button *, void * ) std::cerr << "Tried to set new state to " << newState << std::endl; } -void -setPowerMode( const std::string &mode ) -{ - ( *powerMode.at( mode ) )->setonly(); - std::thread bg{ [mode]{ system( ( "powerprofilesctl set " + mode ).c_str() ); } }; - bg.detach(); -} - void saverChosen() { @@ -200,42 +171,3 @@ perfChosen() { setPowerMode( "performance" ); } - -namespace -{ - void - changeBrightness( int pct ) - { - std::ifstream i_max{ C::path / config->get( "backlight_path" ) / "max_brightness" }; - - int max; - i_max >> max; - - // Clamp to never hit 0 backlight or pass max. - int adj= std::clamp( max * pct / 100, 1, max ); - std::cerr << "Adjustment computed: " << adj << std::endl; - - std::ofstream out{ C::path / config->get( "backlight_path" ) / "brightness" }; - out << adj; - } - - void - increaseBrightness( int pct ) - { - changeBrightness( pct ); - } - - void - decreaseBrightness( int pct ) - { - changeBrightness( -pct ); - } -} - -void -adjustBrightness( MouseWheelSlider *, void * ) -{ - const int amount= brightness->value(); - std::cerr << "Adjusting brightness by " << amount << std::endl; - changeBrightness( amount ); -} diff --git a/power_profile.cc b/power_profile.cc new file mode 100644 index 0000000..d9b2a93 --- /dev/null +++ b/power_profile.cc @@ -0,0 +1,38 @@ +#include "power_profile.h" + +#include +#include + +#include "power_console.h" + + +const std::map< std::string, Fl_Round_Button ** > powerMode= +{ + { "power-saver", &saver }, + { "balanced", &balance }, + { "performance", &perfButton }, +}; + + +// Since this requires launching bg processes, we only do it at startup and then every 30s. +void +profileUpdate( void * ) +{ + FILE *prof= popen( "powerprofilesctl get", "r" ); + char buffer[ 1024 ]= ""; + fscanf( prof, "%s", buffer ); + pclose( prof ); + + ( *powerMode.at( buffer ) )->setonly(); + + Fl::repeat_timeout( 30, profileUpdate, nullptr ); +} + + +void +setPowerMode( const std::string &mode ) +{ + ( *powerMode.at( mode ) )->setonly(); + std::thread bg{ [mode]{ system( ( "powerprofilesctl set " + mode ).c_str() ); } }; + bg.detach(); +} diff --git a/power_profile.h b/power_profile.h new file mode 100644 index 0000000..19fff28 --- /dev/null +++ b/power_profile.h @@ -0,0 +1,8 @@ +#pragma once + +#include + +// Since this requires launching bg processes, we only do it at startup and then every 30s. +void profileUpdate( void * ); + +void setPowerMode( const std::string &mode );