aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore9
-rw-r--r--Makefile80
-rw-r--r--config.mk8
-rw-r--r--libradharc.c171
-rw-r--r--libradharc.h796
-rw-r--r--mk/linux.mk6
-rw-r--r--mk/macos.mk6
-rw-r--r--mk/windows.mk6
-rw-r--r--radharc-ipc.c50
-rw-r--r--radharc.14
-rw-r--r--radharc.c38
11 files changed, 1141 insertions, 33 deletions
diff --git a/.gitignore b/.gitignore
index c36cd0a..cab952b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,5 +3,14 @@
*.o
*.a
*.su
+*.lo
+*.so
+*.so.*
+*.dll
+*.dylib
+*.gch
+*.gcov
+*.gcno
+*.gcda
radharc
radharc-ipc
diff --git a/Makefile b/Makefile
index 7240daf..2395037 100644
--- a/Makefile
+++ b/Makefile
@@ -3,50 +3,106 @@
CONFIGFILE = config.mk
include $(CONFIGFILE)
+OS = linux
+# Linux: linux
+# Mac OS: macos
+# Windows: windows
+include mk/$(OS).mk
+
+
+LIB_MAJOR = 1
+LIB_MINOR = 3
+LIB_VERSION = $(LIB_MAJOR).$(LIB_MINOR)
+LIB_NAME = radharc
+
+
OBJ_RADHARC =\
cg-base.o\
radharc.o
+HDR_RADHARC =\
+ cg-base.h\
+ libradharc.h
+
+
OBJ_RADHARC_IPC =\
radharc-ipc.o
-HDR_RADHARC =\
- cg-base.h
+HDR_RADHARC_IPC =\
+ libradharc.h
+
+
+OBJ_LIBRADHARC =\
+ libradharc.o
+
+HDR_LIBRADHARC =\
+ libradharc.h
+
+
+LOBJ = $(OBJ_LIBRADHARC:.o=.lo)
+
CPPFLAGS_MACROS =\
-D'PACKAGE_NAME="$(PACKAGE_NAME)"'\
-D'COMMAND_NAME="$(COMMAND_NAME)"'
-all: radharc radharc-ipc
+
+all: libradharc.a libradharc.$(LIBEXT) radharc radharc-ipc
$(OBJ_RADHARC): $(HDR_RADHARC)
+$(OBJ_RADHARC_IPC): $(HDR_RADHARC_IPC)
+$(OBJ_LIBRADHARC): $(HDR_LIBRADHARC)
.c.o:
$(CC) -c -o $@ $< $(CPPFLAGS_MACROS) $(CPPFLAGS) $(CFLAGS)
+.c.lo:
+ $(CC) -fPIC -c -o $@ $< $(CFLAGS) $(CPPFLAGS)
+
radharc: $(OBJ_RADHARC)
$(CC) -o $@ $(OBJ_RADHARC) $(LDFLAGS)
-radharc-ipc: $(OBJ_RADHARC_IPC)
- $(CC) -o $@ $(OBJ_RADHARC_IPC) $(LDFLAGS)
+radharc-ipc: $(OBJ_RADHARC_IPC) libradharc.a
+ $(CC) -o $@ $(OBJ_RADHARC_IPC) libradharc.a $(LDFLAGS_IPC)
+
+libradharc.a: $(OBJ_LIBRADHARC)
+ @rm -f -- $@
+ $(AR) rc $@ $(OBJ_LIBRADHARC)
+ $(AR) ts $@ > /dev/null
+
+libradharc.$(LIBEXT): $(LOBJ)
+ $(CC) $(LIBFLAGS) -o $@ $(LOBJ) $(LDFLAGS_LIB)
-install: radharc radharc-ipc
+install: libradharc.a libradharc.$(LIBEXT) radharc radharc-ipc
mkdir -p -- "$(DESTDIR)$(PREFIX)/bin"
mkdir -p -- "$(DESTDIR)$(MANPREFIX)/man1"
- cp -- radharc "$(DESTDIR)$(PREFIX)/bin/"
- cp -- radharc-ipc "$(DESTDIR)$(PREFIX)/bin/"
- cp -- radharc.1 "$(DESTDIR)$(MANPREFIX)/man1/"
- cp -- radharc-ipc.1 "$(DESTDIR)$(MANPREFIX)/man1/"
+ cp -- radharc radharc-ipc "$(DESTDIR)$(PREFIX)/bin/"
+ cp -- radharc.1 radharc-ipc.1 "$(DESTDIR)$(MANPREFIX)/man1/"
+ mkdir -p -- "$(DESTDIR)$(PREFIX)/lib"
+ mkdir -p -- "$(DESTDIR)$(PREFIX)/include"
+ cp -- libradharc.a "$(DESTDIR)$(PREFIX)/lib/"
+ cp -- libradharc.$(LIBEXT) "$(DESTDIR)$(PREFIX)/lib/libradharc.$(LIBMINOREXT)"
+ $(FIX_INSTALL_NAME) "$(DESTDIR)$(PREFIX)/lib/libradharc.$(LIBMINOREXT)"
+ ln -sf -- libradharc.$(LIBMINOREXT) "$(DESTDIR)$(PREFIX)/lib/libradharc.$(LIBMAJOREXT)"
+ ln -sf -- libradharc.$(LIBMAJOREXT) "$(DESTDIR)$(PREFIX)/lib/libradharc.$(LIBEXT)"
+ cp -- libradharc.h "$(DESTDIR)$(PREFIX)/include/"
uninstall:
-rm -f -- "$(DESTDIR)$(PREFIX)/bin/radharc"
-rm -f -- "$(DESTDIR)$(PREFIX)/bin/radharc-ipc"
-rm -f -- "$(DESTDIR)$(MANPREFIX)/man1/radharc.1"
-rm -f -- "$(DESTDIR)$(MANPREFIX)/man1/radharc-ipc.1"
+ -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libradharc.a"
+ -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libradharc.$(LIBMAJOREXT)"
+ -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libradharc.$(LIBMINOREXT)"
+ -rm -f -- "$(DESTDIR)$(PREFIX)/lib/libradharc.$(LIBEXT)"
+ -rm -f -- "$(DESTDIR)$(PREFIX)/include/libradharc.h"
clean:
- -rm -f -- radharc radharc-ipc *.o
+ -rm -f -- *.o *.a *.lo *.su *.so *.so.* *.dll *.dylib
+ -rm -f -- *.gch *.gcov *.gcno *.gcda *.$(LIBEXT)
+ -rm -f -- radharc radharc-ipc
.SUFFIXES:
-.SUFFIXES: .c .o
+.SUFFIXES: .lo .o .c
.PHONY: all check install uninstall clean
diff --git a/config.mk b/config.mk
index 2707eac..f36afb6 100644
--- a/config.mk
+++ b/config.mk
@@ -3,9 +3,11 @@ MANPREFIX = $(PREFIX)/share/man
CC = c99
-CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE
-CFLAGS = -Wall -O2
-LDFLAGS = -lcoopgamma -lred -lm -s
+CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE
+CFLAGS = -Wall -O2
+LDFLAGS = -lcoopgamma -lred -lm -s
+LDFLAGS_IPC = -s
+LDFLAGS_LIB =
PACKAGE_NAME = radharc
COMMAND_NAME = radharc
diff --git a/libradharc.c b/libradharc.c
new file mode 100644
index 0000000..32b47d9
--- /dev/null
+++ b/libradharc.c
@@ -0,0 +1,171 @@
+/* See LICENSE file for copyright and license details. */
+#include "libradharc.h"
+#include <stdarg.h>
+
+
+int
+libradharc_parse_response(const void *msg, size_t msglen, struct libradharc_response *response_out)
+{
+ const unsigned char *m = msg;
+ int enum_value;
+ int64_t i64;
+ int32_t i32;
+
+ if (!msg || !msglen || !response_out) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ response_out->type = (enum libradharc_response_type)*m++;
+ msglen--;
+
+ switch (response_out->type) {
+ case LIBRADHARC_RESPONSE_UNSUPPORTED:
+ case LIBRADHARC_RESPONSE_INVALID_REQUEST:
+ case LIBRADHARC_RESPONSE_ACK:
+ case LIBRADHARC_RESPONSE_ACK_NOOP:
+ case LIBRADHARC_RESPONSE_UNSET:
+ case LIBRADHARC_RESPONSE_YES:
+ case LIBRADHARC_RESPONSE_NO:
+ if (msglen)
+ goto ebadmsg;
+ break;
+
+ case LIBRADHARC_RESPONSE_ERROR_STRING:
+ case LIBRADHARC_RESPONSE_SET_STRING:
+ if (!msglen || m[--msglen] || memchr(m, 0, msglen))
+ goto ebadmsg;
+ response_out->value.string = (const char *)m;
+ break;
+
+ case LIBRADHARC_RESPONSE_SET_TIME:
+ if (msglen != sizeof(i64) + sizeof(i32))
+ goto ebadmsg;
+ memcpy(&i64, &m[0], sizeof(i64));
+ memcpy(&i32, &m[sizeof(i64)], sizeof(i32));
+ response_out->value.time.tv_sec = (time_t)i64;
+ response_out->value.time.tv_nsec = i32;
+ if (response_out->value.time.tv_sec < 0 ||
+ response_out->value.time.tv_nsec < 0 ||
+ response_out->value.time.tv_nsec >= 1000000000L)
+ goto ebadmsg;
+ break;
+
+ case LIBRADHARC_RESPONSE_SET_REAL:
+ if (msglen != sizeof(response_out->value.real))
+ goto ebadmsg;
+ goto raw;
+
+ case LIBRADHARC_RESPONSE_SET_REAL_PAIR:
+ if (msglen != sizeof(response_out->value.real_pair))
+ goto ebadmsg;
+ goto raw;
+
+ case LIBRADHARC_RESPONSE_SET_SIGNED64:
+ if (msglen != sizeof(response_out->value.signed64))
+ goto ebadmsg;
+ raw:
+ memcpy(&response_out->value, m, msglen);
+ break;
+
+ case LIBRADHARC_RESPONSE_SET_ENUM:
+ if (msglen != sizeof(enum_value))
+ goto ebadmsg;
+ memcpy(&enum_value, m, sizeof(enum_value));
+ response_out->value.operation_mode = (enum libradharc_operation_mode)enum_value; /* any enum */
+ break;
+
+ default:
+ ebadmsg:
+ errno = EBADMSG;
+ return -1;
+ }
+
+ return 0;
+}
+
+
+size_t
+libradharc_format_request__n__(void *buffer, enum libradharc_request_type type, int what, size_t n, ...)
+{
+ char *buf = buffer;;
+ size_t off = 0;
+ const char *value;
+ size_t size;
+ va_list args;
+ va_start(args, n);
+
+ if (buf)
+ buf[off] = (char)((n << 4) | type);
+ off++;
+
+ if (buf)
+ buf[off] = (char)what;
+ off++;
+
+ while (n--) {
+ value = va_arg(args, const char *);
+ size = va_arg(args, size_t);
+ if (buf)
+ memcpy(&buf[off], value, size);
+ off += size;
+ }
+
+ va_end(args);
+ return off;
+}
+
+
+extern inline size_t libradharc_format_request__0__(void *, enum libradharc_request_type, int);
+extern inline size_t libradharc_format_request__1__(void *, enum libradharc_request_type, int, const void *, size_t);
+extern inline size_t libradharc_format_request__2__(void *, enum libradharc_request_type, int, const void *, size_t,
+ const void *, size_t);
+extern inline size_t libradharc_format_request__3__(void *, enum libradharc_request_type, int, const void *, size_t,
+ const void *, size_t, const void *, size_t);
+
+extern inline size_t libradharc_format_get_request__0__(void *, enum libradharc_property );
+extern inline size_t libradharc_format_get_request__s__(void *, enum libradharc_property , const char *);
+extern inline size_t libradharc_format_set_request__64i__(void *, enum libradharc_property, int64_t);
+extern inline size_t libradharc_format_set_request__i__(void *, enum libradharc_property, int);
+extern inline size_t libradharc_format_set_request__r__(void *, enum libradharc_property, double);
+extern inline size_t libradharc_format_set_request__rt__(void *, enum libradharc_property, double, const struct timespec *);
+extern inline size_t libradharc_format_set_request__rr__(void *, enum libradharc_property, double, double);
+extern inline size_t libradharc_format_set_request__s__(void *, enum libradharc_property, const char *);
+extern inline size_t libradharc_format_set_request__ss__(void *, enum libradharc_property, const char *, const char *);
+extern inline size_t libradharc_format_set_request__t__(void *, enum libradharc_property, const struct timespec *);
+extern inline size_t libradharc_format_unset_request__0__(void *, enum libradharc_property);
+extern inline size_t libradharc_format_signal_request__0__(void *, int);
+extern inline size_t libradharc_format_signal_request__t__(void *, int, const struct timespec *);
+
+extern inline size_t libradharc_format_set_request__rnt__(void *, enum libradharc_property, double, const struct timespec *);
+extern inline size_t libradharc_format_set_request__sns__(void *, enum libradharc_property, const char *, const char *);
+extern inline size_t libradharc_format_signal_request__nt__(void *, int, const struct timespec *);
+
+extern inline size_t libradharc_format_set_fade_in(void *, const struct timespec *);
+extern inline size_t libradharc_format_get_fade_in(void *);
+extern inline size_t libradharc_format_set_fade_out(void *, const struct timespec *);
+extern inline size_t libradharc_format_get_fade_out(void *);
+extern inline size_t libradharc_format_set_high_temperature(void *, double);
+extern inline size_t libradharc_format_get_high_temperature(void *);
+extern inline size_t libradharc_format_set_low_temperature(void *, double);
+extern inline size_t libradharc_format_get_low_temperature(void *);
+extern inline size_t libradharc_format_set_high_elevation(void *, double);
+extern inline size_t libradharc_format_get_high_elevation(void *);
+extern inline size_t libradharc_format_set_low_elevation(void *, double);
+extern inline size_t libradharc_format_get_low_elevation(void *);
+extern inline size_t libradharc_format_set_location(void *, double, double);
+extern inline size_t libradharc_format_get_location(void *);
+extern inline size_t libradharc_format_unset_location(void *);
+extern inline size_t libradharc_format_set_operation_mode(void *, enum libradharc_operation_mode);
+extern inline size_t libradharc_format_get_operation_mode(void *);
+extern inline size_t libradharc_format_set_temperature(void *, double, const struct timespec *);
+extern inline size_t libradharc_format_get_temperature(void *);
+extern inline size_t libradharc_format_set_priority(void *, int64_t);
+extern inline size_t libradharc_format_get_priority(void *);
+extern inline size_t libradharc_format_set_vendor_option(void *, const char *, const char *);
+extern inline size_t libradharc_format_get_vendor_option(void *, const char *);
+extern inline size_t libradharc_format_get_status(void *);
+extern inline size_t libradharc_format_smooth_terminate(void *, const struct timespec *);
+extern inline size_t libradharc_format_freeze_terminate(void *);
+extern inline size_t libradharc_format_disable(void *, const struct timespec *);
+extern inline size_t libradharc_format_enable(void *, const struct timespec *);
diff --git a/libradharc.h b/libradharc.h
new file mode 100644
index 0000000..ee00b09
--- /dev/null
+++ b/libradharc.h
@@ -0,0 +1,796 @@
+/* See LICENSE file for copyright and license details. */
+#ifndef LIBRADHARC_H
+#define LIBRADHARC_H
+
+#include <errno.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <time.h>
+
+
+enum libradharc_property {
+ LIBRADHARC_PROPERTY_FADE_IN,
+ LIBRADHARC_PROPERTY_FADE_OUT,
+ LIBRADHARC_PROPERTY_HIGH_TEMPERATURE,
+ LIBRADHARC_PROPERTY_LOW_TEMPERATURE,
+ LIBRADHARC_PROPERTY_HIGH_ELEVATION,
+ LIBRADHARC_PROPERTY_LOW_ELEVATION,
+ LIBRADHARC_PROPERTY_LOCATION,
+ LIBRADHARC_PROPERTY_OPERATION_MODE,
+ LIBRADHARC_PROPERTY_TEMPERATURE,
+ LIBRADHARC_PROPERTY_PRIORITY,
+ LIBRADHARC_PROPERTY_VENDOR_OPTION,
+ LIBRADHARC_PROPERTY_STATUS
+};
+
+enum libradharc_request_type {
+ LIBRADHARC_REQUEST_GET,
+ LIBRADHARC_REQUEST_SET,
+ LIBRADHARC_REQUEST_UNSET,
+ LIBRADHARC_REQUEST_SIGNAL
+};
+
+/**
+ * How radharc determines which colour temperature to apply
+ */
+enum libradharc_operation_mode {
+ /**
+ * A specific colour temperature has been selected
+ */
+ LIBRADHARC_OPERATION_STATIC,
+
+ /**
+ * A colour temperature range has been selected
+ * along with a range of solar elevations and the
+ * user's location. The temperature is changed
+ * gradually by mapping to current solar elevation's
+ * position in the range of solar elevations
+ * (clips to the range's boundaries) to a colour
+ * temperature, in corresponding position, the
+ * colour temperature range.
+ */
+ LIBRADHARC_OPERATION_BY_SOLAR_ELEVATION
+};
+
+/**
+ * Request response type
+ */
+enum libradharc_response_type {
+ /**
+ * The made request was invalid
+ */
+ LIBRADHARC_RESPONSE_INVALID_REQUEST,
+
+ /**
+ * Value sent with the request was unsupported
+ */
+ LIBRADHARC_RESPONSE_UNSUPPORTED,
+
+ /**
+ * Action performed
+ */
+ LIBRADHARC_RESPONSE_ACK,
+
+ /**
+ * No action to perform
+ */
+ LIBRADHARC_RESPONSE_ACK_NOOP,
+
+ /**
+ * The requested property is not set
+ */
+ LIBRADHARC_RESPONSE_UNSET,
+
+ /**
+ * The requested property is set to the true boolean value
+ */
+ LIBRADHARC_RESPONSE_YES,
+
+ /**
+ * The requested property is set to the false boolean value
+ */
+ LIBRADHARC_RESPONSE_NO,
+
+ /**
+ * A server-side error was encountered
+ */
+ LIBRADHARC_RESPONSE_ERROR_STRING,
+
+ /**
+ * The requested property is set, and has a string value
+ */
+ LIBRADHARC_RESPONSE_SET_STRING,
+
+ /**
+ * The requested property is set, and has a time duration
+ */
+ LIBRADHARC_RESPONSE_SET_TIME,
+
+ /**
+ * The requested property is set, and has a real value
+ */
+ LIBRADHARC_RESPONSE_SET_REAL,
+
+ /**
+ * The requested property is set, and has two real values
+ *
+ * For the geographical location, this would be the the
+ * latitude as the first value, and a the longitude as
+ * the second value
+ */
+ LIBRADHARC_RESPONSE_SET_REAL_PAIR,
+
+ /**
+ * The requested property is set, and has a signed
+ * 64-bit integer value
+ */
+ LIBRADHARC_RESPONSE_SET_SIGNED64,
+
+ /**
+ * The requested property is set, and has a named value
+ */
+ LIBRADHARC_RESPONSE_SET_ENUM
+};
+
+/**
+ * Response from radharc
+ */
+struct libradharc_response {
+ /**
+ * Response from radharc or indicate of
+ * type used for the response
+ */
+ enum libradharc_response_type type;
+
+ /**
+ * Value send back by radharc
+ *
+ * Only set if `.type` has one of the values
+ * listed the union member fields. The following
+ * values of `.type` do not have an associated
+ * value:
+ * - `LIBRADHARC_RESPONSE_INVALID_REQUEST`
+ * - `LIBRADHARC_RESPONSE_UNSUPPORTED`
+ * - `LIBRADHARC_RESPONSE_ACK`
+ * - `LIBRADHARC_RESPONSE_ACK_NOOP`
+ * - `LIBRADHARC_RESPONSE_UNSET`
+ * - `LIBRADHARC_RESPONSE_YES`
+ * - `LIBRADHARC_RESPONSE_NO`
+ */
+ union {
+ /**
+ * Use if `.type` is `LIBRADHARC_RESPONSE_SET_STRING` or
+ * `LIBRADHARC_RESPONSE_ERROR_STRING`
+ */
+ const char *string;
+
+ /**
+ * Use if `.type` is `LIBRADHARC_RESPONSE_SET_TIME`
+ */
+ struct timespec time;
+
+ /**
+ * Use if `.type` is `LIBRADHARC_RESPONSE_SET_REAL`
+ */
+ double real;
+
+ /**
+ * Use if `.type` is `LIBRADHARC_RESPONSE_SET_REAL_PAIR`
+ */
+ double real_pair[2];
+
+ /**
+ * Use if `.type` is `LIBRADHARC_RESPONSE_SET_SIGNED64`
+ */
+ int64_t signed64;
+
+ /**
+ * Use if `.type` is `LIBRADHARC_RESPONSE_SET_ENUM`,
+ * and the response is for a get-request for radharc's
+ * operation mode
+ */
+ enum libradharc_operation_mode operation_mode;
+ } value;
+};
+
+
+/**
+ * Parse a response from radharc
+ *
+ * All requests generate a response, which are sent in order
+ *
+ * @param msg The received message
+ * @param msglen The length of the message
+ * @param response_out Output parameter for the prased message
+ * @return 0 on success, -1 on failure
+ *
+ * @throws EINVAL `msglen` is 0
+ * @throws EINVAL `msg` is `NULL`
+ * @throws EINVAL `response_out` is `NULL`
+ * @throws EBADMSG The received message is invalid
+ */
+int libradharc_parse_response(const void *msg, size_t msglen, struct libradharc_response *response_out);
+
+
+size_t libradharc_format_request__n__(void *buffer, enum libradharc_request_type type, int what, size_t n, ...);
+
+inline size_t
+libradharc_format_request__0__(void *buffer, enum libradharc_request_type type, int what)
+{
+ return libradharc_format_request__n__(buffer, type, what, 0);
+}
+
+inline size_t
+libradharc_format_request__1__(void *buffer, enum libradharc_request_type type, int what,
+ const void *value1, size_t size1)
+{
+ return libradharc_format_request__n__(buffer, type, what, 1, value1, size1);
+}
+
+inline size_t
+libradharc_format_request__2__(void *buffer, enum libradharc_request_type type, int what,
+ const void *value1, size_t size1,
+ const void *value2, size_t size2)
+{
+ return libradharc_format_request__n__(buffer, type, what, 2, value1, size1, value2, size2);
+}
+
+inline size_t
+libradharc_format_request__3__(void *buffer, enum libradharc_request_type type, int what,
+ const void *value1, size_t size1,
+ const void *value2, size_t size2,
+ const void *value3, size_t size3)
+{
+ return libradharc_format_request__n__(buffer, type, what, 3, value1, size1, value2, size2, value3, size3);
+}
+
+inline size_t
+libradharc_format_get_request__0__(void *buffer, enum libradharc_property property)
+{
+ return libradharc_format_request__0__(buffer, LIBRADHARC_REQUEST_GET, (int)property);
+}
+
+inline size_t
+libradharc_format_get_request__s__(void *buffer, enum libradharc_property property, const char *arg1)
+{
+ if (!arg1) {
+ errno = EINVAL;
+ return 0;
+ }
+ return libradharc_format_request__1__(buffer, LIBRADHARC_REQUEST_GET, (int)property, arg1, strlen(arg1) + 1U);
+}
+
+inline size_t
+libradharc_format_set_request__64i__(void *buffer, enum libradharc_property property, int64_t arg1)
+{
+ return libradharc_format_request__1__(buffer, LIBRADHARC_REQUEST_SET, (int)property, &arg1, sizeof(arg1));
+}
+
+inline size_t
+libradharc_format_set_request__i__(void *buffer, enum libradharc_property property, int arg1)
+{
+ return libradharc_format_request__1__(buffer, LIBRADHARC_REQUEST_SET, (int)property, &arg1, sizeof(arg1));
+}
+
+inline size_t
+libradharc_format_set_request__r__(void *buffer, enum libradharc_property property, double arg1)
+{
+ return libradharc_format_request__1__(buffer, LIBRADHARC_REQUEST_SET, (int)property, &arg1, sizeof(arg1));
+}
+
+inline size_t
+libradharc_format_set_request__rt__(void *buffer, enum libradharc_property property, double arg1, const struct timespec *arg2)
+{
+ if (!arg2 || arg2->tv_sec < 0 || arg2->tv_nsec < 0 || arg2->tv_nsec >= 1000000000L) {
+ errno = EINVAL;
+ return 0;
+ }
+ return libradharc_format_request__3__(buffer, LIBRADHARC_REQUEST_SET, property,
+ &arg1, sizeof(arg1),
+ &arg2->tv_sec, sizeof(arg2->tv_sec),
+ &arg2->tv_nsec, sizeof(arg2->tv_nsec));
+}
+
+inline size_t
+libradharc_format_set_request__rr__(void *buffer, enum libradharc_property property, double arg1, double arg2)
+{
+ return libradharc_format_request__2__(buffer, LIBRADHARC_REQUEST_SET, (int)property,
+ &arg1, sizeof(arg1), &arg2, sizeof(arg2));
+}
+
+inline size_t
+libradharc_format_set_request__s__(void *buffer, enum libradharc_property property, const char *arg1)
+{
+ if (!arg1) {
+ errno = EINVAL;
+ return 0;
+ }
+ return libradharc_format_request__1__(buffer, LIBRADHARC_REQUEST_SET, (int)property,
+ arg1, strlen(arg1) + 1U);
+}
+
+inline size_t
+libradharc_format_set_request__ss__(void *buffer, enum libradharc_property property, const char *arg1, const char *arg2)
+{
+ if (!arg1 || !arg2) {
+ errno = EINVAL;
+ return 0;
+ }
+ return libradharc_format_request__2__(buffer, LIBRADHARC_REQUEST_SET, (int)property,
+ arg1, strlen(arg1) + 1U, arg2, strlen(arg2) + 1U);
+}
+
+inline size_t
+libradharc_format_set_request__t__(void *buffer, enum libradharc_property property, const struct timespec *arg1)
+{
+ if (!arg1 || arg1->tv_sec < 0 || arg1->tv_nsec < 0 || arg1->tv_nsec >= 1000000000L) {
+ errno = EINVAL;
+ return 0;
+ }
+ return libradharc_format_request__2__(buffer, LIBRADHARC_REQUEST_SET, (int)property,
+ &arg1->tv_sec, sizeof(arg1->tv_sec),
+ &arg1->tv_nsec, sizeof(arg1->tv_nsec));
+}
+
+inline size_t
+libradharc_format_unset_request__0__(void *buffer, enum libradharc_property property)
+{
+ return libradharc_format_request__0__(buffer, LIBRADHARC_REQUEST_UNSET, (int)property);
+}
+
+inline size_t
+libradharc_format_signal_request__0__(void *buffer, int signal)
+{
+ return libradharc_format_request__0__(buffer, LIBRADHARC_REQUEST_SIGNAL, signal);
+}
+
+inline size_t
+libradharc_format_signal_request__t__(void *buffer, int signal, const struct timespec *arg1)
+{
+ if (!arg1 || arg1->tv_sec < 0 || arg1->tv_nsec < 0 || arg1->tv_nsec >= 1000000000L) {
+ errno = EINVAL;
+ return 0;
+ }
+ return libradharc_format_request__2__(buffer, LIBRADHARC_REQUEST_SIGNAL, signal,
+ &arg1->tv_sec, sizeof(arg1->tv_sec),
+ &arg1->tv_nsec, sizeof(arg1->tv_nsec));
+}
+
+
+inline size_t
+libradharc_format_set_request__rnt__(void *buffer, enum libradharc_property property, double arg1, const struct timespec *arg2)
+{
+ if (arg2)
+ return libradharc_format_set_request__rt__(buffer, property, arg1, arg2);
+ else
+ return libradharc_format_set_request__r__(buffer, property, arg1);
+}
+
+inline size_t
+libradharc_format_set_request__sns__(void *buffer, enum libradharc_property property, const char *arg1, const char *arg2)
+{
+ if (arg2)
+ return libradharc_format_set_request__ss__(buffer, property, arg1, arg2);
+ else
+ return libradharc_format_set_request__s__(buffer, property, arg1);
+}
+
+inline size_t
+libradharc_format_signal_request__nt__(void *buffer, int signal, const struct timespec *arg1)
+{
+ if (arg1)
+ return libradharc_format_signal_request__t__(buffer, signal, arg1);
+ else
+ return libradharc_format_signal_request__0__(buffer, signal);
+}
+
+
+/**
+ * Format a message that instructs radharc to reconfigure
+ * its effect fade-in time
+ *
+ * It is unspecified how this effects any ongoing fade-in
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param duration The new fade duration
+ * @return The size of the message, 0 on failure
+ *
+ * @throws EINVAL `duration` is `NULL`
+ * @throws EINVAL `duration->tv_nsec` is invalid
+ * @throws EINVAL `duration->tv_sec` is negative
+ */
+inline size_t
+libradharc_format_set_fade_in(void *buffer, const struct timespec *duration)
+{ return libradharc_format_set_request__t__(buffer, LIBRADHARC_PROPERTY_FADE_IN, duration); }
+
+/**
+ * Format a message that instructs radharc to send back
+ * its currently configured effect fade-in time
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_get_fade_in(void *buffer)
+{ return libradharc_format_get_request__0__(buffer, LIBRADHARC_PROPERTY_FADE_IN); }
+
+
+/**
+ * Format a message that instructs radharc to reconfigure
+ * its effect fade-out time
+ *
+ * It is unspecified how this effects any ongoing fade-out
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param duration The new fade duration
+ * @return The size of the message, 0 on failure
+ *
+ * @throws EINVAL `duration` is `NULL`
+ * @throws EINVAL `duration->tv_nsec` is invalid
+ * @throws EINVAL `duration->tv_sec` is negative
+ */
+inline size_t
+libradharc_format_set_fade_out(void *buffer, const struct timespec *duration)
+{ return libradharc_format_set_request__t__(buffer, LIBRADHARC_PROPERTY_FADE_OUT, duration); }
+
+/**
+ * Format a message that instructs radharc to send back
+ * its currently configured effect fade-out time
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_get_fade_out(void *buffer)
+{ return libradharc_format_get_request__0__(buffer, LIBRADHARC_PROPERTY_FADE_OUT); }
+
+
+/**
+ * Format a message that instructs radharc to configure
+ * the colour temperature that shall be applied
+ * when the Sun's elevation at least at the configured
+ * upper threshold of twilight, that at daytime after
+ * daybreak
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param temperature The colour temperature, in Kelvins, must be at least 1000
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_set_high_temperature(void *buffer, double temperature)
+{ return libradharc_format_set_request__r__(buffer, LIBRADHARC_PROPERTY_HIGH_TEMPERATURE, temperature); }
+
+/**
+ * Format a message that instructs radharc to send back
+ * its configured colour temperature that shall be applied
+ * when the Sun's elevation at least at the configured
+ * upper threshold of twilight, that at daytime after
+ * daybreak
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_get_high_temperature(void *buffer)
+{ return libradharc_format_get_request__0__(buffer, LIBRADHARC_PROPERTY_HIGH_TEMPERATURE); }
+
+
+/**
+ * Format a message that instructs radharc to configure
+ * the colour temperature that shall be applied
+ * when the Sun's elevation at most at the configured
+ * lower threshold of twilight, that at nighttime after
+ * nightfall
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param temperature The colour temperature, in Kelvins, must be at least 1000
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_set_low_temperature(void *buffer, double temperature)
+{ return libradharc_format_set_request__r__(buffer, LIBRADHARC_PROPERTY_LOW_TEMPERATURE, temperature); }
+
+/**
+ * Format a message that instructs radharc to send back
+ * its configured colour temperature that shall be applied
+ * when the Sun's elevation at most at the configured
+ * lower threshold of twilight, that at nighttime after
+ * nightfall
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_get_low_temperature(void *buffer)
+{ return libradharc_format_get_request__0__(buffer, LIBRADHARC_PROPERTY_LOW_TEMPERATURE); }
+
+
+/**
+ * Format a message that instructs radharc to configure
+ * the upper theshold of twilight, that is, the solar
+ * elevation that marks the end of daybreak and the
+ * beginning of nightfall
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param degrees The solar elevation, in degrees
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_set_high_elevation(void *buffer, double degrees)
+{ return libradharc_format_set_request__r__(buffer, LIBRADHARC_PROPERTY_HIGH_ELEVATION, degrees); }
+
+/**
+ * Format a message that instructs radharc to send back
+ * its configured upper theshold of twilight, that is,
+ * the solar elevation that marks the end of daybreak
+ * and the beginning of nightfall
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_get_high_elevation(void *buffer)
+{ return libradharc_format_get_request__0__(buffer, LIBRADHARC_PROPERTY_HIGH_ELEVATION); }
+
+
+/**
+ * Format a message that instructs radharc to configure
+ * the lower theshold of twilight, that is, the solar
+ * elevation that marks the end of nightfall and the
+ * beginning of daybreak
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param degrees The solar elevation, in degrees
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_set_low_elevation(void *buffer, double degrees)
+{ return libradharc_format_set_request__r__(buffer, LIBRADHARC_PROPERTY_LOW_ELEVATION, degrees); }
+
+/**
+ * Format a message that instructs radharc to send back
+ * its configured lower theshold of twilight, that is,
+ * the solar elevation that marks the end of nightfall
+ * and the beginning of daybreak
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_get_low_elevation(void *buffer)
+{ return libradharc_format_get_request__0__(buffer, LIBRADHARC_PROPERTY_LOW_ELEVATION); }
+
+
+/**
+ * Format a message that instructs radharc to reconfigured
+ * the geographical location
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param latitude The new latitude, in degrees north of the equator according to GPS
+ * @param longitude The new longitude, in degrees east of the prime meridian according to GPS
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_set_location(void *buffer, double latitude, double longitude)
+{ return libradharc_format_set_request__rr__(buffer, LIBRADHARC_PROPERTY_LOCATION, latitude, longitude); }
+
+/**
+ * Format a message that instructs radharc to send back
+ * its currently configured geographical location
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_get_location(void *buffer)
+{ return libradharc_format_get_request__0__(buffer, LIBRADHARC_PROPERTY_LOCATION); }
+
+/**
+ * Format a message that instructs radharc remove its
+ * currently configured geolocation, causing it to
+ * freeze at the current temperature, until modified
+ * or a new location is set, unless another operation
+ * mode that doesn't need the user's location is being
+ * used
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_unset_location(void *buffer)
+{ return libradharc_format_unset_request__0__(buffer, LIBRADHARC_PROPERTY_LOCATION); }
+
+
+/**
+ * Format a message that instructs radharc to use another
+ * operation mode
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param mode The new operation mode
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_set_operation_mode(void *buffer, enum libradharc_operation_mode mode)
+{ return libradharc_format_set_request__i__(buffer, LIBRADHARC_PROPERTY_OPERATION_MODE, (int)mode); }
+
+/**
+ * Format a message that instructs radharc to send back
+ * its currently configured operation mode
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_get_operation_mode(void *buffer)
+{ return libradharc_format_get_request__0__(buffer, LIBRADHARC_PROPERTY_OPERATION_MODE); }
+
+
+/**
+ * Format a message that instructs radharc to apply
+ * a specific colour temperature
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param temperature The temperature to apply, in Kelvins, must be at least 1000
+ * @param transition_duration The transition time, or `NULL` to use the configured fade time
+ * (it's implementation specific how it is defined)
+ * @return The size of the message, 0 on failure
+ *
+ * Implementations of radharc need not implement support for
+ * smooth temperature transitions, so `transition_duration`
+ * may be ignored
+ */
+inline size_t
+libradharc_format_set_temperature(void *buffer, double temperature, const struct timespec *transition_duration)
+{ return libradharc_format_set_request__rnt__(buffer, LIBRADHARC_PROPERTY_TEMPERATURE, temperature, transition_duration); }
+
+/**
+ * Format a message that instructs radharc to send back
+ * its currently applied temperature
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_get_temperature(void *buffer)
+{ return libradharc_format_get_request__0__(buffer, LIBRADHARC_PROPERTY_TEMPERATURE); }
+
+
+/**
+ * Format a message that instructs radharc to reconfigure
+ * its effect priority
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param priority The new priority
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_set_priority(void *buffer, int64_t priority)
+{ return libradharc_format_set_request__64i__(buffer, LIBRADHARC_PROPERTY_PRIORITY, priority); }
+
+/**
+ * Format a message that instructs radharc to send back
+ * its currently configured effect priority
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_get_priority(void *buffer)
+{ return libradharc_format_get_request__0__(buffer, LIBRADHARC_PROPERTY_PRIORITY); }
+
+
+/**
+ * Format a message that instructs radharc to apply
+ * or modify an implemenation specific setting
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param option The name of the option
+ * @param value The value for the option, or `NULL` if there is none
+ * @return The size of the message, 0 on failure
+ *
+ * @throws EINVAL `option` is `NULL`
+ */
+inline size_t
+libradharc_format_set_vendor_option(void *buffer, const char *option, const char *value)
+{ return libradharc_format_set_request__sns__(buffer, LIBRADHARC_PROPERTY_VENDOR_OPTION, option, value); }
+
+/**
+ * Format a message that instructs radharc to send
+ * back the value of a implemenation specific setting
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param option The name of the option
+ * @return The size of the message, 0 on failure
+ *
+ * @throws EINVAL `option` is `NULL`
+ */
+inline size_t
+libradharc_format_get_vendor_option(void *buffer, const char *option)
+{ return libradharc_format_get_request__s__(buffer, LIBRADHARC_PROPERTY_VENDOR_OPTION, option); }
+
+
+/**
+ * Format a message that instructs radharc to send back
+ * its current status
+ *
+ * radharc will respond with an with a single-line string,
+ * but it's content is implementation defined
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_get_status(void *buffer)
+{ return libradharc_format_get_request__0__(buffer, LIBRADHARC_PROPERTY_STATUS); }
+
+
+/**
+ * Format a message that instructs radharc to fade out its
+ * effect and terminate
+ *
+ * Sending this message is equivalent to sending SIGINT once,
+ * except the transition duration can be overridden ad hoc,
+ * or twice if `transition_duration` is `{0, 0}`
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param transition_duration The transition time, or `NULL` to use the configured fade out time
+ * @return The size of the message, 0 on failure
+ *
+ * @throws EINVAL `transition_duration->tv_nsec` is invalid
+ * @throws EINVAL `transition_duration->tv_sec` is negative
+ */
+inline size_t
+libradharc_format_smooth_terminate(void *buffer, const struct timespec *transition_duration)
+{ return libradharc_format_signal_request__nt__(buffer, SIGINT, transition_duration); }
+
+/**
+ * Format a message that instructs radharc to, once any
+ * current transition has take place, terminate without
+ * restoring the colour temperature
+ *
+ * Sending this message is equivalent to sending SIGHUP
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @return The size of the message, 0 on failure
+ */
+inline size_t
+libradharc_format_freeze_terminate(void *buffer)
+{ return libradharc_format_signal_request__0__(buffer, SIGHUP); }
+
+/**
+ * Format a message that instructs radharc to disable itself
+ *
+ * Sending this message is equivalent to sending SIGUSR1,
+ * except the transition duration can be overridden ad hoc
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param transition_duration The transition time, or `NULL` to use the configured fade out time
+ * @return The size of the message, 0 on failure
+ *
+ * @throws EINVAL `transition_duration->tv_nsec` is invalid
+ * @throws EINVAL `transition_duration->tv_sec` is negative
+ */
+inline size_t
+libradharc_format_disable(void *buffer, const struct timespec *transition_duration)
+{ return libradharc_format_signal_request__nt__(buffer, SIGUSR1, transition_duration); }
+
+/**
+ * Format a message that instructs radharc to enable itself
+ *
+ * Sending this message is equivalent to sending SIGUSR2,
+ * except the transition duration can be overridden ad hoc
+ *
+ * @param buffer Output buffer for the message, or `NULL` to measure the required size
+ * @param transition_duration The transition time, or `NULL` to use the configured fade in time
+ * @return The size of the message, 0 on failure
+ *
+ * @throws EINVAL `transition_duration->tv_nsec` is invalid
+ * @throws EINVAL `transition_duration->tv_sec` is negative
+ */
+inline size_t
+libradharc_format_enable(void *buffer, const struct timespec *transition_duration)
+{ return libradharc_format_signal_request__nt__(buffer, SIGUSR2, transition_duration); }
+
+#endif
diff --git a/mk/linux.mk b/mk/linux.mk
new file mode 100644
index 0000000..ad58f69
--- /dev/null
+++ b/mk/linux.mk
@@ -0,0 +1,6 @@
+LIBEXT = so
+LIBFLAGS = -shared -Wl,-soname,lib$(LIB_NAME).$(LIBEXT).$(LIB_MAJOR)
+LIBMAJOREXT = $(LIBEXT).$(LIB_MAJOR)
+LIBMINOREXT = $(LIBEXT).$(LIB_VERSION)
+
+FIX_INSTALL_NAME = :
diff --git a/mk/macos.mk b/mk/macos.mk
new file mode 100644
index 0000000..670ad0d
--- /dev/null
+++ b/mk/macos.mk
@@ -0,0 +1,6 @@
+LIBEXT = dylib
+LIBFLAGS = -dynamiclib -Wl,-compatibility_version,$(LIB_MAJOR) -Wl,-current_version,$(LIB_VERSION)
+LIBMAJOREXT = $(LIB_MAJOR).$(LIBEXT)
+LIBMINOREXT = $(LIB_VERSION).$(LIBEXT)
+
+FIX_INSTALL_NAME = install_name_tool -id "$(PREFIX)/lib/libradharc.$(LIBMAJOREXT)"
diff --git a/mk/windows.mk b/mk/windows.mk
new file mode 100644
index 0000000..ed5ec8d
--- /dev/null
+++ b/mk/windows.mk
@@ -0,0 +1,6 @@
+LIBEXT = dll
+LIBFLAGS = -shared
+LIBMAJOREXT = $(LIB_MAJOR).$(LIBEXT)
+LIBMINOREXT = $(LIB_VERSION).$(LIBEXT)
+
+FIX_INSTALL_NAME = :
diff --git a/radharc-ipc.c b/radharc-ipc.c
index 83f436f..3787d2d 100644
--- a/radharc-ipc.c
+++ b/radharc-ipc.c
@@ -11,11 +11,13 @@
#include <string.h>
#include <unistd.h>
+#include "libradharc.h"
+
USAGE("[-R rule] (pid | @name | &fd | address) ...");
struct message {
- char *text;
+ void *text;
size_t len;
};
@@ -46,7 +48,7 @@ main(int argc, char *argv[])
size_t i, j;
struct sockaddr_un addr;
size_t addrlen;
- int sock;
+ int sock, *socks;
struct message *messages = NULL;
size_t nmessages = 0;
@@ -70,9 +72,24 @@ main(int argc, char *argv[])
if (!addresses)
goto fail;
+ sock = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (sock < 0)
+ goto fail;
+
+ /* we need an address, otherwise the peer will not get an address to send the response to */
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_family = AF_UNIX;
+ if (bind(sock, (void *)&addr, (socklen_t)offsetof(struct sockaddr_un, sun_path)))
+ goto fail;
+
+ socks = calloc((size_t)argc, sizeof(int));
+ if (!socks)
+ goto fail;
+
for (i = 0; i < (size_t)argc; i++) {
const char *arg = argv[i];
uintmax_t num;
+ socks[i] = sock;
if (*arg == '@' || strchr(arg, '/')) {
addresses[i] = strdup(arg);
if (addresses[i])
@@ -83,11 +100,8 @@ main(int argc, char *argv[])
if (*arg == '&') {
if (num > (uintmax_t)INT_MAX)
usage();
- /* TODO whoops, this should be send with that fd, not to it */
- addresses[i] = malloc(sizeof("/proc/self/fd/") + strlen(&arg[1]));
- if (!addresses[i])
- goto fail;
- stpcpy(stpcpy(addresses[i], "/proc/self/fd/"), &arg[1]);
+ addresses[i] = NULL;
+ socks[i] = (int)num;
} else {
addresses[i] = malloc(sizeof("@/proc//") + strlen(arg) + strlen(class));
if (!addresses[i])
@@ -105,15 +119,11 @@ main(int argc, char *argv[])
}
}
- sock = socket(PF_UNIX, SOCK_DGRAM, 0);
- if (sock < 0)
- goto fail;
-
for (j = 0; j < nmessages; j++) {
for (i = 0; i < (size_t)argc; i++) {
size_t len;
- if (!addresses[i])
+ if (socks[i] < 0)
continue;
len = strlen(&addresses[i][1]) + 1U;
@@ -122,15 +132,26 @@ main(int argc, char *argv[])
memcpy(addr.sun_path, addresses[i], len);
addrlen = offsetof(struct sockaddr_un, sun_path) + len;
- if (sendto(sock, messages[j].text, messages[j].len, MSG_NOSIGNAL,
+ if (socks[i] != sock) {
+ if (send(socks[i], messages[j].text, messages[j].len, MSG_NOSIGNAL) < 0)
+ goto send_failed;
+ } else if (sendto(sock, messages[j].text, messages[j].len, MSG_NOSIGNAL,
(void *)&addr, (socklen_t)addrlen) < 0) {
+ send_failed:
fprintf(stderr, "%s: error while sending to '%s': %s\n",
argv0, argv[i], strerror(errno));
ret = 1;
- addresses[i] = NULL;
+ socks[i] = -1;
}
}
free(messages[j].text);
+
+ for (i = 0; i < (size_t)argc; i++) {
+ if (socks[i] < 0)
+ continue;
+
+ /* TODO get response */
+ }
}
close(sock);
@@ -140,6 +161,7 @@ main(int argc, char *argv[])
free(addresses);
free(messages);
free(class);
+ free(socks);
return ret;
fail:
diff --git a/radharc.1 b/radharc.1
index dba2623..fca875c 100644
--- a/radharc.1
+++ b/radharc.1
@@ -43,7 +43,7 @@ but uses
.BR libcoopgamma (7)
to allow it to be used alongside other programs that also
modify the monitors colour output, as long as the also use
-.RB libcoopgamma (7).
+.BR libcoopgamma (7).
.SH OPTIONS
The following options are supported:
@@ -234,7 +234,7 @@ sent twice, the effect is removed immediately.
.TP
.B SIGHUP
Terminate the process after any current fade in or fade
-out action, but leaf the effect in place.
+out action, but leave the effect in place.
.TP
.B SIGUSR1
Gradually fade out the effect but do not terminate the process.
diff --git a/radharc.c b/radharc.c
index e48dc6f..08ccc2f 100644
--- a/radharc.c
+++ b/radharc.c
@@ -1,5 +1,6 @@
/* See LICENSE file for copyright and license details. */
#include "cg-base.h"
+#include "libradharc.h"
#include <sys/socket.h>
#include <sys/timerfd.h>
@@ -20,6 +21,20 @@
/**
+ * Possible states of the program
+ */
+enum state {
+ INITIALISING,
+ INITIAL_FADE_IN,
+ TERMINAL_FADE_OUT,
+ ENABLE_FADE_IN,
+ DISABLE_FADE_OUT,
+ ENABLED_NORMAL,
+ DISABLED
+};
+
+
+/**
* The default filter priority for the program
*/
const int64_t default_priority = (int64_t)7 << 61;
@@ -133,6 +148,11 @@ static const char *sockname = NULL;
*/
static int no_temperature_change = 0;
+/**
+ * The state the program is in
+ */
+static enum state current_state = INITIALISING;
+
/**
* If 0, SIGINT has not been received,
@@ -694,12 +714,15 @@ read_socket(int sock)
{
char buffer[64];
ssize_t r;
+ struct sockaddr_un addr;
+ socklen_t addrlen;
if (sock < 0)
return;
for (;;) {
- r = recv(sock, buffer, sizeof(buffer), MSG_DONTWAIT | MSG_TRUNC);
+ addrlen = SOCKLEN(addr);
+ r = recvfrom(sock, buffer, sizeof(buffer), MSG_DONTWAIT | MSG_TRUNC, &addr, &addrlen);
if (r < 0) {
if (errno == EAGAIN)
break;
@@ -710,11 +733,17 @@ read_socket(int sock)
}
if (!r || (size_t)r > sizeof(buffer)) {
- fprintf(stderr, "%s: invalid length of received message: %zi\n", argv0, r);
+ if (addrlen) {
+ /* TODO send LIBRADHARC_RESPONSE_INVALID_REQUEST */
+ }
continue;
}
/* TODO parse message */
+
+ if (addrlen) {
+ /* TODO send response */
+ }
}
}
@@ -877,11 +906,13 @@ fade_in:
fade_cs = (size_t)fade_in_cs;
if (initial_fade_in) {
+ current_state = INITIAL_FADE_IN;
initial_fade_in = 0;
if ((r = get_temperature(&target_temperature)) < 0)
return r;
} else {
fade_in_have_timer:
+ current_state = ENABLE_FADE_IN;
original_temperature = 6500;
}
for (i = 0; i < fade_cs;) {
@@ -923,6 +954,7 @@ skip_fade_in:
faded_in:
+ current_state = ENABLED_NORMAL;
for (;;) {
read_socket(sock);
if (sigint_received) {
@@ -975,6 +1007,7 @@ fade_out:
fade_cs = (size_t)fade_out_cs;
fade_out_have_timer:
+ current_state = (sigint_received || sighup_received) ? TERMINAL_FADE_OUT : DISABLE_FADE_OUT;
original_temperature = current_temperature;
for (i = 0; i < fade_cs;) {
read_socket(sock);
@@ -1010,6 +1043,7 @@ skip_fade_out:
faded_out:
+ current_state = DISABLED;
for (i = 0; i < filters_n; i++)
crtc_updates[i].filter.lifespan = LIBCOOPGAMMA_REMOVE;
if ((r = set_ramps(red, green, blue)) < 0)