diff options
-rw-r--r-- | DEPENDENCIES | 4 | ||||
-rw-r--r-- | Makefile | 8 | ||||
-rw-r--r-- | TODO | 1 | ||||
-rw-r--r-- | src/blueshift_iccprofile.c | 212 |
4 files changed, 221 insertions, 4 deletions
diff --git a/DEPENDENCIES b/DEPENDENCIES index 398b703..4e9e9d3 100644 --- a/DEPENDENCIES +++ b/DEPENDENCIES @@ -1,7 +1,7 @@ RUNTIME DEPENDENCIES: python3 - libxcb (opt-out, for randr and crtc identification) + libxcb (opt-out, for randr, crtc identification and icc profile listing) libx11 (opt-out, for vidmode) libxxf86vm (opt-out, for vidmode) argparser-python (https://github.com/maandree/argparser) @@ -12,7 +12,7 @@ MAKE DEPENDENCIES: cython c99 (a C 99 compliant compiler; provided by gcc) python3 - libxcb (opt-out, for randr and crtc identification) + libxcb (opt-out, for randr, crtc identification and icc profile listing) libx11 (opt-out, for vidmode) libxxf86vm (opt-out, for vidmode) make @@ -39,7 +39,7 @@ PKGNAME ?= blueshift # Bindings for display server access SERVER_BINDINGS ?= randr vidmode # Executable bindings for display server access -EXECS ?= idcrtc +EXECS ?= idcrtc iccprofile # Executable library files EXECLIBS = $(foreach E,$(EXECS),blueshift_$(E)) @@ -52,6 +52,7 @@ WARN = -Wall -Wextra -pedantic # The C standard for C code compilation STD = c99 LIBS_idcrtc = xcb-randr +LIBS_iccprofile = xcb LIBS_randr = xcb-randr LIBS_vidmode = x11 xxf86vm LIBS = python3 $(foreach B,$(SERVER_BINDINGS) $(EXECS),$(LIBS_$(B))) @@ -87,6 +88,11 @@ bin/blueshift_idcrtc: obj/blueshift_idcrtc.o @mkdir -p bin $(CC) $(FLAGS) $$($(PKGCONFIG) --libs $($(LIBS_))) -o $@ $^ +bin/blueshift_iccprofile: LIBS_=LIBS_iccprofile +bin/blueshift_iccprofile: obj/blueshift_iccprofile.o + @mkdir -p bin + $(CC) $(FLAGS) $$($(PKGCONFIG) --libs $($(LIBS_))) -o $@ $^ + bin/blueshift_randr.so: LIBS_=LIBS_randr bin/blueshift_vidmode.so: LIBS_=LIBS_vidmode bin/%.so: obj/%.o obj/%_c.o @@ -4,7 +4,6 @@ Medium priority: Low priority: Fix errors caused by SIGUSR2 - http://www.oyranos.org/wiki/index.php?title=ICC_Profiles_in_X_Specification_0.2 Add support for monitor hotplugging Add backlight support Add wayland support diff --git a/src/blueshift_iccprofile.c b/src/blueshift_iccprofile.c new file mode 100644 index 0000000..152b547 --- /dev/null +++ b/src/blueshift_iccprofile.c @@ -0,0 +1,212 @@ +/** + * Copyright © 2014 Mattias Andrée (maandree@member.fsf.org) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ +#define _GNU_SOURCE /* for strcasestr */ +#include <stdlib.h> +#include <stdio.h> +#include <alloca.h> +#include <string.h> + +#include <xcb/xcb.h> + + + +/** + * Connection to the X server + */ +static xcb_connection_t* connection; + +/** + * Used to store errors in + */ +static xcb_generic_error_t* error; + + + +/** + * Main entry point of the program + * + * @param argc Length of `argv` + * @param argv Command line arguments + * @return Zero on success + */ +int main(int argc, char** argv) +{ + const xcb_setup_t* setup; + xcb_screen_iterator_t iter; + int screen_count; + xcb_screen_t* screens; + int screen_i; + + (void) argc; + (void) argv; + + + /* Get X connection */ + + connection = xcb_connect(NULL, NULL); + + + /* Get screen information */ + + setup = xcb_get_setup(connection); + iter = xcb_setup_roots_iterator(setup); + screen_count = iter.rem; + screens = iter.data; + + for (screen_i = 0; screen_i < screen_count; screen_i++) + { + xcb_screen_t* screen = screens + screen_i; + xcb_list_properties_cookie_t list_cookie; + xcb_list_properties_reply_t* list_reply; + xcb_atom_t* atoms; + xcb_atom_t* atoms_end; + + + /* Get root window properties */ + + list_cookie = xcb_list_properties(connection, screen->root); + list_reply = xcb_list_properties_reply(connection, list_cookie, &error); + + if (error) + { + fprintf(stderr, "Screen root window property list query returned %i\n", error->error_code); + xcb_disconnect(connection); + return 1; + } + + atoms = xcb_list_properties_atoms(list_reply); + atoms_end = atoms + xcb_list_properties_atoms_length(list_reply); + + for (; atoms != atoms_end; atoms++) + { + xcb_get_atom_name_cookie_t name_cookie; + xcb_get_atom_name_reply_t* name_reply; + char* name; + char* name_; + int len; + xcb_get_property_cookie_t prop_cookie; + xcb_get_property_reply_t* prop_reply; + int monitor; + + + /* Get root window property name */ + + name_cookie = xcb_get_atom_name(connection, *atoms); + name_reply = xcb_get_atom_name_reply(connection, name_cookie, &error); + + if (error) + { + fprintf(stderr, "Screen root window property name query returned %i\n", error->error_code); + free(list_reply); + xcb_disconnect(connection); + return 1; + } + + name_ = xcb_get_atom_name_name(name_reply); + len = xcb_get_atom_name_name_length(name_reply); + + name = alloca((len + 1) * sizeof(char)); + memcpy(name, name_, len * sizeof(char)); + *(name + len) = 0; + free(name_reply); + + + /* Check property name pattern */ + + if (!strcmp(name, "_icc_profile")) + monitor = 0; + else if (strcasestr(name, "_icc_profile_") == name) + { + name += strlen("_icc_profile_"); + monitor = 0; + if (*name) + continue; + while (*name) + { + char c = *name; + if (('0' <= c) && (c <= '9')) + monitor = monitor * 10 - (c & 15); + else + goto monitor_bad; + } + monitor = -monitor; + goto monitor_ok; + + monitor_bad: + continue; + } + else + continue; + + + /* Get root window property value */ + + monitor_ok: + prop_cookie = xcb_get_property(connection, 0, screen->root, *atoms, XCB_GET_PROPERTY_TYPE_ANY, 0, 0); + prop_reply = xcb_get_property_reply(connection, prop_cookie, &error); + + if (error) + { + fprintf(stderr, "Screen root window property value query returned %i\n", error->error_code); + free(prop_reply); + free(list_reply); + xcb_disconnect(connection); + return 1; + } + + len = prop_reply->bytes_after; + free(prop_reply); + + prop_cookie = xcb_get_property(connection, 0, screen->root, *atoms, XCB_GET_PROPERTY_TYPE_ANY, 0, len); + prop_reply = xcb_get_property_reply(connection, prop_cookie, &error); + + if (error) + { + fprintf(stderr, "Screen root window property value query returned %i\n", error->error_code); + free(prop_reply); + free(list_reply); + xcb_disconnect(connection); + return 1; + } + + { + char* value = alloca((len + 1) * sizeof(char)); + char* value_ = xcb_get_property_value(prop_reply); + + memcpy(value, value_, len); + *(value + len) = 0; + + printf("%i: %i: %s", screen_i, monitor, value); + fflush(stdout); + putchar('\0'); + putchar('\n'); + } + + free(prop_reply); + } + + free(list_reply); + } + + fflush(stdout); + + /* Free resources **/ + + xcb_disconnect(connection); + return 0; +} + |