-
Notifications
You must be signed in to change notification settings - Fork 10
/
screen.c
155 lines (131 loc) · 4.56 KB
/
screen.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#ifdef SCREEN_PRESENT
#include "screen.h"
#include "bus_utils.h"
#define MONITOR_ILL_MAX 255
static int method_getbrightness(sd_bus_message *m, void *userdata, sd_bus_error *ret_error);
static screen_plugin *plugins[SCREEN_NUM];
static const char object_path[] = "/org/clightd/clightd/Screen";
static const char bus_interface[] = "org.clightd.clightd.Screen";
static const sd_bus_vtable vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_METHOD("GetEmittedBrightness", "ss", "d", method_getbrightness, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_VTABLE_END
};
MODULE("SCREEN");
static void module_pre_start(void) {
}
static bool check(void) {
return true;
}
static bool evaluate(void) {
return true;
}
static void init(void) {
int r = sd_bus_add_object_vtable(bus,
NULL,
object_path,
bus_interface,
vtable,
NULL);
for (int i = 0; i < SCREEN_NUM && !r; i++) {
if (plugins[i]) {
snprintf(plugins[i]->obj_path, sizeof(plugins[i]->obj_path) - 1, "%s/%s", object_path, plugins[i]->name);
r += sd_bus_add_object_vtable(bus,
NULL,
plugins[i]->obj_path,
bus_interface,
vtable,
plugins[i]);
}
}
if (r < 0) {
m_log("Failed to issue method call: %s\n", strerror(-r));
}
}
static void receive(const msg_t *msg, const void *userdata) {
}
static void destroy(void) {
}
void screen_register_new(screen_plugin *plugin) {
const char *plugins_names[] = {
#define X(name, val) #name,
_SCREEN_PLUGINS
#undef X
};
int i;
for (i = 0; i < SCREEN_NUM; i++) {
if (strcasestr(plugins_names[i], plugin->name)) {
break;
}
}
if (i < SCREEN_NUM) {
plugins[i] = plugin;
printf("Registered '%s' screen plugin.\n", plugin->name);
} else {
printf("Screen plugin '%s' not recognized. Not registering.\n", plugin->name);
}
}
int rgb_frame_brightness(const uint8_t *data, const int width, const int height, const int stride) {
/*
* takes 1 pixel every div*div area
* (div values > 8 will almost not give performance improvements)
*/
int r = 0, g = 0, b = 0;
const int div = 8;
const int wmax = (double)width / div;
const int hmax = (double)height / div;
const int pixelsize = (double)stride / width;
for (int i = 0; i < wmax; i++) {
for (int k = 0; k < hmax; k++) {
/* obtain r,g,b components */
const uint8_t *p = data + (i * div * pixelsize + k * div * stride);
r += p[2] & 0xFF;
g += p[1] & 0xFF;
b += p[0] & 0xFF;
}
}
const int area = wmax * hmax;
r = (double)r / area;
g = (double)g / area;
b = (double)b / area;
/* https://en.wikipedia.org/wiki/Rec._709#luma_coefficients */
/* https://www.itu.int/dms_pubrec/itu-r/rec/bt/R-REC-BT.709-6-201506-I!!PDF-E.pdf */
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}
static int method_getbrightness(sd_bus_message* m, void* userdata, sd_bus_error* ret_error) {
const char *display = NULL, *env = NULL;
/* Read the parameters */
int r = sd_bus_message_read(m, "ss", &display, &env);
if (r < 0) {
m_log("Failed to parse parameters: %s\n", strerror(-r));
return r;
}
bus_sender_fill_creds(m);
screen_plugin *plugin = userdata;
int br = WRONG_PLUGIN;
if (!plugin) {
for (int i = 0; i < SCREEN_NUM && br == WRONG_PLUGIN; i++) {
br = plugins[i]->get(display, env);
}
} else {
br = plugin->get(display, env);
}
if (br < 0) {
switch (br) {
case -EINVAL:
sd_bus_error_set_errno(ret_error, -br);
break;
case COMPOSITOR_NO_PROTOCOL:
sd_bus_error_set_const(ret_error, SD_BUS_ERROR_FAILED, "Compositor does not support 'wlr-screencopy-unstable-v1' protocol.");
break;
case WRONG_PLUGIN:
sd_bus_error_set_const(ret_error, SD_BUS_ERROR_FAILED, "No plugin available for your configuration.");
break;
case -EIO:
sd_bus_error_set_errno(ret_error, EIO);
}
return -EACCES;
}
return sd_bus_reply_method_return(m, "d", (double)br / MONITOR_ILL_MAX);
}
#endif