#include #include #include #include #include #include #define BREATHING_INTERVAL 90 // in milliseconds #define STRESS_THRESHOLD 8.0 // System load threshold for stress mode // Default and stress colors const char *default_colors[] = { "#ffe667", // Yellow "#f27049", // Orange "#3dd762" // Green }; const char *stress_colors[] = { "#f60000", // Bright Red "#8e0000", // Dark Red "#a10000", // Muted Red "#5a0000" // Deep Crimson }; // Convert sRGB to Linear RGB double srgb_to_linear(double value) { if (value <= 0.04045) return value / 12.92; else return pow((value + 0.055) / 1.055, 2.4); } // Convert Linear RGB to sRGB double linear_to_srgb(double value) { if (value <= 0.0031308) return value * 12.92; else return 1.055 * pow(value, 1.0 / 2.4) - 0.055; } // Function to interpolate between two colors in linear RGB space void interpolate_color(const char *color1, const char *color2, double t, char *output) { unsigned int r1, g1, b1, r2, g2, b2; double lr1, lg1, lb1, lr2, lg2, lb2, lr, lg, lb; // Parse the input hex colors sscanf(color1, "#%02x%02x%02x", &r1, &g1, &b1); sscanf(color2, "#%02x%02x%02x", &r2, &g2, &b2); // Convert sRGB to linear RGB lr1 = srgb_to_linear(r1 / 255.0); lg1 = srgb_to_linear(g1 / 255.0); lb1 = srgb_to_linear(b1 / 255.0); lr2 = srgb_to_linear(r2 / 255.0); lg2 = srgb_to_linear(g2 / 255.0); lb2 = srgb_to_linear(b2 / 255.0); // Interpolate in linear RGB space lr = lr1 + t * (lr2 - lr1); lg = lg1 + t * (lg2 - lg1); lb = lb1 + t * (lb2 - lb1); // Convert back to sRGB r1 = round(linear_to_srgb(lr) * 255); g1 = round(linear_to_srgb(lg) * 255); b1 = round(linear_to_srgb(lb) * 255); // Output the interpolated color as hex snprintf(output, 8, "#%02x%02x%02x", r1, g1, b1); } // Function to read system load double get_system_load() { double load; FILE *f = fopen("/proc/loadavg", "r"); if (f) { fscanf(f, "%lf", &load); fclose(f); } else { perror("Failed to read /proc/loadavg"); load = 0.0; } return load; } // Function to update breathing color void update_breathing_color() { static int color_index = 0; static double t = 0.0; char new_color[8]; // Determine the current color set (default or stress) const char **current_colors; int num_colors; if (get_system_load() > STRESS_THRESHOLD) { current_colors = stress_colors; num_colors = sizeof(stress_colors) / sizeof(stress_colors[0]); } else { current_colors = default_colors; num_colors = sizeof(default_colors) / sizeof(default_colors[0]); } // Interpolate between the current and next color in the palette interpolate_color( current_colors[color_index], current_colors[(color_index + 1) % num_colors], t, new_color ); // Write the new color to the output file FILE *f = fopen("/tmp/breathing_color", "w"); if (f) { fprintf(f, "%s\n", new_color); fclose(f); } // Update interpolation factor and color index t += 0.02; // Adjust speed of interpolation here if (t >= 1.0) { t = 0.0; color_index = (color_index + 1) % num_colors; } } int main() { struct timespec last_breathing_update = {0}, now; // Initialize breathing colors clock_gettime(CLOCK_MONOTONIC, &last_breathing_update); while (1) { clock_gettime(CLOCK_MONOTONIC, &now); // Update breathing colors double elapsed_breathing = (now.tv_sec - last_breathing_update.tv_sec) * 1000.0 + (now.tv_nsec - last_breathing_update.tv_nsec) / 1.0e6; if (elapsed_breathing >= BREATHING_INTERVAL) { update_breathing_color(); last_breathing_update = now; } usleep(10000); // Sleep to prevent excessive CPU usage } return 0; }