Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 51 additions & 36 deletions brightnessctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,18 @@ static bool ensure_dev_dir(struct device *);
static bool logind_set_brightness(struct device *);
#endif

#define min(a, b) ({ \
__auto_type _a = (a); \
__auto_type _b = (b); \
_a < _b ? _a : _b; })

#define max(a, b) ({ \
__auto_type _a = (a); \
__auto_type _b = (b); \
_a > _b ? _a : _b; })

#define clamp(val, lo, hi) min(max(val, lo), hi)

struct device {
char *class;
char *id;
Expand All @@ -75,9 +87,8 @@ struct device {
bool matches;
};

enum value_type { ABSOLUTE, RELATIVE };
enum delta_type { DIRECT, DELTA };
enum sign { PLUS, MINUS };
enum value_type { ABSOLUTE, PERCENT };
enum delta_type { DIRECT, PLUS, MINUS };

struct value {
union {
Expand All @@ -86,7 +97,6 @@ struct value {
};
enum value_type v_type;
enum delta_type d_type;
enum sign sign;
};

enum operation { INFO, GET, MAX, SET, RESTORE };
Expand Down Expand Up @@ -138,7 +148,7 @@ int main(int argc, char **argv) {
int ret = 0;
int n, c, phelp = 0;
p.exponent = 1;
p.min = (struct value){ .val = 0, .v_type = ABSOLUTE, .d_type = DIRECT, .sign = PLUS };
p.min = (struct value){ .val = 0, .v_type = ABSOLUTE, .d_type = DIRECT };
while ((c = getopt_long(argc, argv, "lqpmPn::e::srhVc:d:", options, NULL)) >= 0) {
switch (c) {
case 'l':
Expand All @@ -164,10 +174,10 @@ int main(int argc, char **argv) {
break;
case 'n':
if (optarg) {
if (!parse_value(&p.min, optarg) || p.min.sign == MINUS)
if (!parse_value(&p.min, optarg) || p.min.d_type == MINUS)
fail("Invalid min-value given\n");
} else if (NULL != argv[optind] && '-' != argv[optind][0]) {
if (!parse_value(&p.min, argv[optind++]) || p.min.sign == MINUS)
if (!parse_value(&p.min, argv[optind++]) || p.min.d_type == MINUS)
fail("Invalid min-value given\n");
} else {
p.min.val = 1;
Expand Down Expand Up @@ -325,31 +335,27 @@ bool parse_value(struct value *val, char *str) {
errno = 0;
val->v_type = ABSOLUTE;
val->d_type = DIRECT;
val->sign = PLUS;
if (!str || !*str)
return false;
if (*str == '+' || *str == '-') {
val->sign = *str == '+' ? PLUS : MINUS;
val->d_type = DELTA;
val->d_type = *str == '+' ? PLUS : MINUS;
str++;
}
n = strtod(str, &buf);
if (errno || buf == str)
return false;
while ((c = *(buf++))) switch(c) {
case '+':
val->sign = PLUS;
val->d_type = DELTA;
val->d_type = PLUS;
break;
case '-':
val->sign = MINUS;
val->d_type = DELTA;
val->d_type = MINUS;
break;
case '%':
val->v_type = RELATIVE;
val->v_type = PERCENT;
break;
}
if (val->v_type == RELATIVE) {
if (val->v_type == PERCENT) {
val->percentage = n;
} else {
val->val = labs((long) n) % LONG_MAX;
Expand Down Expand Up @@ -397,31 +403,40 @@ void print_device(struct device *dev) {

unsigned int calc_value(struct device *d, struct value *val) {
long new = d->curr_brightness;
if (val->d_type == DIRECT) {
new = val->v_type == ABSOLUTE ? val->val : percent_to_val(val->percentage, d);
goto apply;
}
int sign_mod = val->sign == MINUS ? -1 : 1;
long mod;
if (val->v_type == RELATIVE) {
mod = percent_to_val(val_to_percent(d->curr_brightness, d, false) + val->percentage * sign_mod, d) - d->curr_brightness;
if (val->percentage != 0 && mod == 0)
mod = val->sign == PLUS ? 1 : -1;
if (val->v_type == ABSOLUTE) {
switch (val->d_type) {
case DIRECT:
new = val->val;
break;
case PLUS:
new = d->curr_brightness + val->val;
break;
case MINUS:
new = d->curr_brightness - val->val;
break;
}
} else {
mod = val->val * sign_mod;
float curr_pct = val_to_percent(d->curr_brightness, d, false);
float bias = curr_pct + val->percentage > roundf(curr_pct + val->percentage) ?
-1.0f / d->max_brightness :
1.0f / d->max_brightness;
switch (val->d_type) {
case DIRECT:
new = percent_to_val(val->percentage, d);
break;
case PLUS:
new = percent_to_val(curr_pct + val->percentage + bias, d);
break;
case MINUS:
new = percent_to_val(curr_pct - val->percentage + bias, d);
break;
}
}
new += mod;
apply:
if (p.min.v_type == RELATIVE) {
if (p.min.v_type == PERCENT) {
p.min.val = percent_to_val(p.min.percentage, d);
p.min.v_type = ABSOLUTE;
}
if (new < (long)p.min.val)
new = p.min.val;
if (new < 0)
new = 0;
if (new > d->max_brightness)
new = d->max_brightness;
new = clamp(new, (long)p.min.val, (long)d->max_brightness);
return new;
}

Expand Down