Full Code of d4l3k/go-sct for AI

master bb1dc072d627 cached
26 files
72.2 KB
23.0k tokens
107 symbols
1 requests
Download .txt
Repository: d4l3k/go-sct
Branch: master
Commit: bb1dc072d627
Files: 26
Total size: 72.2 KB

Directory structure:
gitextract_ec4q16gx/

├── .travis.yml
├── Dockerfile
├── LICENSE
├── README.md
├── cmd/
│   ├── sct/
│   │   └── sct.go
│   └── waysct/
│       └── waysct.go
├── geoip/
│   ├── geoip.go
│   └── geoip_test.go
├── go.mod
├── go.sum
├── sct.go
├── sct_nix.go
├── sct_windows.go
├── sctcli/
│   ├── sctcli.go
│   └── sctcli_test.go
├── test.sh
└── waysct/
    ├── gamma-control-client-protocol.h
    ├── gamma-control-protocol.h
    ├── gamma-control.xml
    ├── gamma-wl.h
    ├── orbital-authorizer-client-protocol.h
    ├── orbital-authorizer-protocol.h
    ├── orbital-authorizer.xml
    ├── os-compatibility-impl.h
    ├── os-compatibility.h
    └── waysct.go

================================================
FILE CONTENTS
================================================

================================================
FILE: .travis.yml
================================================
sudo: required

services:
  - docker

language: go
go: 1.10.x

script:
  - docker build -t sct .
  - docker run --rm -it sct ./test.sh

addons:
  apt:
    packages:
    - xorg-dev
    - libglu1-mesa-dev



================================================
FILE: Dockerfile
================================================
FROM golang:1.10

RUN apt-get update && apt-get install -y curl xvfb xorg-dev libglu1-mesa-dev

WORKDIR /go/src/github.com/d4l3k/go-sct
COPY . .

RUN go get -d -v ./...
RUN go install -v ./...


================================================
FILE: LICENSE
================================================
Copyright (C) 2015 Tristan Rice

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
# go-sct [![GoDoc](https://godoc.org/github.com/d4l3k/go-sct?status.svg)](https://godoc.org/github.com/d4l3k/go-sct)

A color temperature setting library and CLI that operates in a similar way to f.lux and Redshift.

The command line app automatically determines your location using GeoIP and adjusts the color temperature depending on time.

For wayland support replace all commands with `waysct` instead of `sct`.

```sh
# For X11 and Windows
$ go install github.com/d4l3k/go-sct/cmd/sct@latest

$ sct # Launch in background
$ sct 3000 # One time temperature change. Temperature must be 1000-10000.

# For Wayland
$ go install github.com/d4l3k/go-sct/cmd/waysct@latest

$ waysct # Launch in background
$ waysct 3000 # One time temperature change. Wayland requires a persistent manager so this will immediately revert.
```

## Windows
By default, the lowest color temperature allowed is around 4500K. More
information is available [here](http://jonls.dk/2010/09/windows-gamma-adjustments/)

There is a workaround to allow all possible adjustments by alterting the registry.

```
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ICM]
"GdiIcmGammaRange"=dword:00000100
```
Save the above as a file with a ".reg" extension and double click to apply.

## Credit
Setting the color temperature uses a port of [sct](http://www.tedunangst.com/flak/post/sct-set-color-temperature) in Go. Credit goes to him for figuring out how to do this.

go-sct also provides the `geoip` package which is a packaged version of
http://devdungeon.com/content/ip-geolocation-go

## License
Made by [Tristan Rice](https://fn.lc).

go-sct is licensed under the MIT license. `geoip` and `sct` are copyrighted by their respective owners.

`waysct` is using code from the redshift implementation and is licensed under
GPLv3. See https://github.com/minus7/redshift/commit/7da875d34854a6a34612d5ce4bd8718c32bec804



================================================
FILE: cmd/sct/sct.go
================================================
package main

import (
	"github.com/d4l3k/go-sct"
	"github.com/d4l3k/go-sct/sctcli"
)

func main() {
	sctcli.Main(func(temp int) error {
		sct.SetColorTemp(temp)
		return nil
	})
}


================================================
FILE: cmd/waysct/waysct.go
================================================
// waysct is a set color temp utility for Wayland.
package main

import (
	"log"

	"github.com/d4l3k/go-sct/sctcli"
	"github.com/d4l3k/go-sct/waysct"
)

func main() {
	m, err := waysct.StartManager()
	if err != nil {
		log.Fatalf("%+v", err)
	}
	defer m.Close()
	sctcli.Main(m.SetColorTemp)
}


================================================
FILE: geoip/geoip.go
================================================
// geoip returns the lat/lng of the target IP address (or current machine)
package geoip

import (
	"encoding/json"
	"fmt"
	"net/http"
)

type GeoIP struct {
	City      string  `json:"city"`
	Latitude  float64 `json:"lat"`
	Longitude float64 `json:"lon"`
}

// LookupIP looks up the geolocation information for the specified address ("" for current host).
func LookupIP(address string) (*GeoIP, error) {
	response, err := http.Get(fmt.Sprintf("http://ip-api.com/json/%s?fields=lat,lon,city", address))
	if err != nil {
		return nil, err
	}
	defer response.Body.Close()

	var geo GeoIP
	if err := json.NewDecoder(response.Body).Decode(&geo); err != nil {
		return nil, err
	}
	return &geo, nil
}


================================================
FILE: geoip/geoip_test.go
================================================
package geoip

import "testing"

func TestLookupIP(t *testing.T) {
	geo, err := LookupIP("")
	if err != nil {
		t.Fatal(err)
	}
	if geo.Latitude == 0 {
		t.Fatalf("expected non empty Latitude: %+v", geo)
	}
	if geo.Longitude == 0 {
		t.Fatalf("expected non empty Longitude: %+v", geo)
	}
}


================================================
FILE: go.mod
================================================
module github.com/d4l3k/go-sct

go 1.16

require (
	github.com/cpucycle/astrotime v0.0.0-20120927164819-9c7d514efdb5
	github.com/pkg/errors v0.9.1
)


================================================
FILE: go.sum
================================================
github.com/cpucycle/astrotime v0.0.0-20120927164819-9c7d514efdb5 h1:Z6YGTs9TwkwIVCltpgUNFa+L5SAyGfIL9gH0RB7yDgw=
github.com/cpucycle/astrotime v0.0.0-20120927164819-9c7d514efdb5/go.mod h1:O+WdStE4WLD+lG5MaDRl9dSJR7w4HZJrJbqVsOEx5Lw=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=


================================================
FILE: sct.go
================================================
package sct

import "runtime"

type color struct {
	r, g, b float64
}

/* cribbed from redshift, but truncated with 500K steps */
var whitepoints = []color{
	{1.00000000, 0.18172716, 0.00000000}, /* 1000K */
	{1.00000000, 0.42322816, 0.00000000},
	{1.00000000, 0.54360078, 0.08679949},
	{1.00000000, 0.64373109, 0.28819679},
	{1.00000000, 0.71976951, 0.42860152},
	{1.00000000, 0.77987699, 0.54642268},
	{1.00000000, 0.82854786, 0.64816570},
	{1.00000000, 0.86860704, 0.73688797},
	{1.00000000, 0.90198230, 0.81465502},
	{1.00000000, 0.93853986, 0.88130458},
	{1.00000000, 0.97107439, 0.94305985},
	{1.00000000, 1.00000000, 1.00000000}, /* 6500K */
	{0.95160805, 0.96983355, 1.00000000},
	{0.91194747, 0.94470005, 1.00000000},
	{0.87906581, 0.92357340, 1.00000000},
	{0.85139976, 0.90559011, 1.00000000},
	{0.82782969, 0.89011714, 1.00000000},
	{0.80753191, 0.87667891, 1.00000000},
	{0.78988728, 0.86491137, 1.00000000}, /* 10000K */
	{0.77442176, 0.85453121, 1.00000000},
}

// SetColorTemp changes the monitor colors to reflect the specified color temperature.
func SetColorTemp(temp int) {
	// An attempt to fix https://github.com/d4l3k/go-sct/issues/9
	if runtime.GOOS == "windows" {
		setColorTemp(temp + 1)
	}
	setColorTemp(temp)
}

func setColorTemp(temp int) {
	if temp < 1000 || temp > 10000 {
		temp = 6500
	}
	temp -= 1000
	ratio := float64((temp-1000)%500) / 500.0
	point := whitepoints[temp/500]
	point1 := whitepoints[(temp/500)+1]
	gammar := point.r*(1-ratio) + point1.r*ratio
	gammag := point.g*(1-ratio) + point1.g*ratio
	gammab := point.b*(1-ratio) + point1.b*ratio
	setColorGamma(gammar, gammag, gammab)
}


================================================
FILE: sct_nix.go
================================================
// +build linux freebsd openbsd

package sct

// #cgo CFLAGS: -I/usr/X11R6/include -I/usr/local/include
// #cgo LDFLAGS: -L/usr/X11R6/lib -L/usr/local/lib -lX11 -lXrandr
// #include <stdio.h>
// #include <strings.h>
// #include <string.h>
// #include <stdlib.h>
// #include <stdint.h>
// #include <inttypes.h>
// #include <stdarg.h>
// #include <math.h>
// #include <X11/Xlib.h>
// #include <X11/Xlibint.h>
// #include <X11/Xproto.h>
// #include <X11/Xatom.h>
// #include <X11/extensions/Xrandr.h>
// #include <X11/extensions/Xrender.h>
// Window RootWindowMacro(Display * dpy, int scr) {
//   return RootWindow(dpy, scr);
// }
// RRCrtc crtcxid(RRCrtc * crtcs, int i) {
//	 return crtcs[i];
// }
// void ushortSet(ushort * s, int k, double v) {
//	 s[k] = (ushort)v;
// }
// ushort* ushortCast(void* s) {
// 	return (ushort*)s;
// }
// int screenCount(Display * dpy) {
//   return XScreenCount(dpy);
// }
import "C"
import "unsafe"

// setColorGamma changes the Xrandr colors to reflect the specified color temperature.
func setColorGamma(gammar, gammag, gammab float64) {
	dpy := C.XOpenDisplay(nil)
	screenCount := C.screenCount(dpy)
	for screen := C.int(0); screen < screenCount; screen++ {
		root := C.RootWindowMacro(dpy, screen)

		res := C.XRRGetScreenResourcesCurrent(dpy, root)

		for c := C.int(0); c < res.ncrtc; c++ {
			crtcxid := C.crtcxid(res.crtcs, c)

			size := C.XRRGetCrtcGammaSize(dpy, crtcxid)
			crtc_gamma := C.XRRAllocGamma(size)
			for i := C.int(0); i < size; i++ {
				g := 65535.0 * float64(i) / float64(size)
				C.ushortSet(C.ushortCast(unsafe.Pointer(crtc_gamma.red)), i, C.double(g*gammar))
				C.ushortSet(C.ushortCast(unsafe.Pointer(crtc_gamma.green)), i, C.double(g*gammag))
				C.ushortSet(C.ushortCast(unsafe.Pointer(crtc_gamma.blue)), i, C.double(g*gammab))
			}
			C.XRRSetCrtcGamma(dpy, crtcxid, crtc_gamma)
			C.XFree(unsafe.Pointer(crtc_gamma))
		}

		C.XFree(unsafe.Pointer(res))
	}
	C.XCloseDisplay(dpy)
}


================================================
FILE: sct_windows.go
================================================
package sct

import (
	"syscall"
	"unsafe"
)

// setColorGamma changes the device gamma curve colors to reflect the specified color temperature.
func setColorGamma(gammar, gammag, gammab float64) {
	user32 := syscall.NewLazyDLL("User32.dll")
	gdi32 := syscall.NewLazyDLL("Gdi32.dll")
	procGetDC := user32.NewProc("GetDC")
	procSetDeviceGammaRamp := gdi32.NewProc("SetDeviceGammaRamp")

	var gamma [3][256]uint16

	for i := 0; i < 256; i++ {
		g := 65535.0 * float64(i) / float64(256)
		gamma[0][i] = uint16(g * gammar)
		gamma[1][i] = uint16(g * gammag)
		gamma[2][i] = uint16(g * gammab)
	}

	hdc, _, _ := procGetDC.Call(uintptr(0))

	procSetDeviceGammaRamp.Call(hdc, uintptr(unsafe.Pointer(&gamma)))
}


================================================
FILE: sctcli/sctcli.go
================================================
package sctcli

import (
	"flag"
	"io/ioutil"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
	"time"

	"github.com/cpucycle/astrotime"
	"github.com/d4l3k/go-sct/geoip"
)

var dayTemp = flag.Int("dayTemp", 6500, "The color temperature during the day.")
var nightTemp = flag.Int("nightTemp", 3000, "The color temperature during the night.")
var daemon = flag.Bool("d", true, "run app as a daemon")
var mode = flag.String("mode", "geoip", "Mode of daemon (geoip or timed). Timed mode uses specified sunrise-time, midday-time, and sunset-time.")
var sunriseTimeStr = flag.String("sunrise-time", "06:30", "Sunrise time (HH:MM)")
var sunsetTimeStr = flag.String("sunset-time", "21:00", "Sunset time (HH:MM)")
var middayTimeStr = flag.String("midday-time", "14:00", "Mid day (brightest) time (HH:MM)")
var midnight, sunriseTime, sunsetTime, middayTime time.Time

func Main(setColorTemp func(temp int) error) {
	c := SCTCLI{
		SetColorTemp: setColorTemp,
	}
	if err := c.Run(); err != nil {
		log.Fatalf("%+v", err)
	}
}

type SCTCLI struct {
	SetColorTemp func(temp int) error
}

func (c SCTCLI) monitorGeo() error {
	log.Printf("Fetching location...")
	geo, err := geoip.LookupIP("")
	if err != nil {
		return err
	}
	log.Printf(" - City: %s, Lat: %f, Lon: %f", geo.City, geo.Latitude, geo.Longitude)
	log.Printf("Monitoring daylight settings...")
	var lastState *bool
	for {
		rise := astrotime.NextSunrise(time.Now(), geo.Latitude, -geo.Longitude)
		set := astrotime.NextSunset(time.Now(), geo.Latitude, -geo.Longitude)
		state := rise.Before(set)
		if lastState != nil && state == *lastState {
			time.Sleep(1 * time.Minute)
			continue
		}
		lastState = &state
		if state {
			log.Print("Good night!")
			if err := c.interpolateColorTemp(*nightTemp); err != nil {
				return err
			}
		} else {
			log.Print("Good morning!")
			if err := c.interpolateColorTemp(*dayTemp); err != nil {
				return err
			}
		}
	}
}

var (
	totalTime = 3 * time.Second
	stepEvery = 1 * time.Second / 60
)

func (c SCTCLI) interpolateColorTemp(new int) error {
	old, err := getCurrentColorTemp()
	if err != nil {
		return err
	}

	steps := int(totalTime / stepEvery)
	stepSize := (new - old) / steps
	for i := 0; i < steps; i++ {
		timer := time.After(stepEvery)
		if err := c.SetColorTemp(old + stepSize*i); err != nil {
			return err
		}
		<-timer
	}
	if err := c.SetColorTemp(new); err != nil {
		return err
	}

	return saveCurrentColorTemp(new)
}

func tempFile() string {
	display := os.Getenv("DISPLAY")
	return filepath.Join(os.TempDir(), "sct-temp-"+display)
}

func saveCurrentColorTemp(temp int) error {
	return ioutil.WriteFile(tempFile(), []byte(strconv.Itoa(temp)), 0644)
}

func getCurrentColorTemp() (int, error) {
	body, err := ioutil.ReadFile(tempFile())
	if os.IsNotExist(err) {
		return *dayTemp, nil
	} else if err != nil {
		return 0, err
	}

	return strconv.Atoi(string(body))
}

func (c SCTCLI) monitorTime() error {
	var monitorTemperature int
	monitorTemperature = 6500

	for {
		curTime := time.Now()
		midnight = time.Date(curTime.Year(), curTime.Month(), curTime.Day(), 0, 0, 0, 0, time.Local)

		// Advance the day?
		if midnight.After(sunsetTime) {
			sunriseTime = sunriseTime.AddDate(0, 0, 1)
			middayTime = middayTime.AddDate(0, 0, 1)
			sunsetTime = sunsetTime.AddDate(0, 0, 1)
		}

		if curTime.After(sunriseTime) && curTime.Before(sunsetTime) {
			if curTime.Before(middayTime) {
				elapsedDuration := curTime.Sub(sunriseTime)
				ratio := float64(elapsedDuration) / float64(middayTime.Sub(sunriseTime))
				monitorTemperature = int(float64(*nightTemp)*(1-ratio) + float64(*dayTemp)*ratio)
			} else {
				elapsedDuration := curTime.Sub(middayTime)
				ratio := float64(elapsedDuration) / float64(sunsetTime.Sub(middayTime))
				monitorTemperature = int(float64(*dayTemp)*(1-ratio) + float64(*nightTemp)*ratio)
			}
		} else {
			monitorTemperature = *nightTemp
		}
		if err := c.SetColorTemp(monitorTemperature); err != nil {
			return err
		}
		time.Sleep(10 * time.Minute)
	}
}

func (c SCTCLI) Run() error {
	flag.Parse()
	args := flag.Args()

	if len(args) == 1 {
		if temp, err := strconv.Atoi(args[0]); err == nil {
			if err := c.interpolateColorTemp(temp); err != nil {
				return err
			}
		}
	} else if len(args) == 0 {
		// Parse time arguments
		curTime := time.Now()
		midnight = time.Date(curTime.Year(), curTime.Month(), curTime.Day(), 0, 0, 0, 0, time.Local)
		var perr error
		if sunriseTime, perr = time.ParseInLocation("2006-01-02 15:04", midnight.Format("2006-01-02 ")+*sunriseTimeStr, time.Local); perr != nil {
			return perr
		}
		if sunsetTime, perr = time.ParseInLocation("2006-01-02 15:04", midnight.Format("2006-01-02 ")+*sunsetTimeStr, time.Local); perr != nil {
			return perr
		}
		if middayTime, perr = time.ParseInLocation("2006-01-02 15:04", midnight.Format("2006-01-02 ")+*middayTimeStr, time.Local); perr != nil {
			return perr
		}

		if *daemon {
			args := os.Args[1:]
			for i := 0; i < len(args); i++ {
				if strings.HasPrefix(args[i], "-d") {
					args[i] = "-d=false"
					break
				}
			}
			args = append(args, "-d=false")
			cmd := exec.Command(os.Args[0], args...)
			cmd.Start()
			log.Println("Launched background process... pid", cmd.Process.Pid)
			os.Exit(0)
		} else {
			switch *mode {
			case "timed":
				if err := c.monitorTime(); err != nil {
					return err
				}
			default:
				if err := c.monitorGeo(); err != nil {
					return err
				}
			}
		}
	}
	return nil
}


================================================
FILE: sctcli/sctcli_test.go
================================================
package sctcli

import (
	"os"
	"testing"
	"time"
)

func setDisplay(val string) func() {
	old := os.Getenv("DISPLAY")
	os.Setenv("DISPLAY", val)
	return func() {
		os.Setenv("DISPLAY", old)
	}
}

func TestGetCurrentColorTemp(t *testing.T) {
	defer setDisplay("testdisplay" + time.Now().String())()

	temp, err := getCurrentColorTemp()
	if err != nil {
		t.Fatal(err)
	}
	if temp != *dayTemp {
		t.Fatalf("expected default day temp")
	}

	for _, want := range []int{3000, 6500} {
		if err := saveCurrentColorTemp(want); err != nil {
			t.Fatal(err)
		}
		temp, err := getCurrentColorTemp()
		if err != nil {
			t.Fatal(err)
		}
		if temp != want {
			t.Fatalf("expected %d temp", want)
		}
	}
}

func TestInterpolate(t *testing.T) {
	totalTime = 100 * time.Millisecond

	c := SCTCLI{SetColorTemp: func(temp int) error { return nil }}

	for _, want := range []int{3000, 6500} {
		if err := c.interpolateColorTemp(want); err != nil {
			t.Fatal(err)
		}
		temp, err := getCurrentColorTemp()
		if err != nil {
			t.Fatal(err)
		}
		if temp != want {
			t.Fatalf("expected %d temp", want)
		}
	}
}


================================================
FILE: test.sh
================================================
#!/bin/bash

xvfb-run go test -v ./...


================================================
FILE: waysct/gamma-control-client-protocol.h
================================================
/* Generated by wayland-scanner 1.19.0 */

#ifndef WLR_GAMMA_CONTROL_UNSTABLE_V1_CLIENT_PROTOCOL_H
#define WLR_GAMMA_CONTROL_UNSTABLE_V1_CLIENT_PROTOCOL_H

#include <stdint.h>
#include <stddef.h>
#include "wayland-client.h"

#ifdef  __cplusplus
extern "C" {
#endif

/**
 * @page page_wlr_gamma_control_unstable_v1 The wlr_gamma_control_unstable_v1 protocol
 * manage gamma tables of outputs
 *
 * @section page_desc_wlr_gamma_control_unstable_v1 Description
 *
 * This protocol allows a privileged client to set the gamma tables for
 * outputs.
 *
 * Warning! The protocol described in this file is experimental and
 * backward incompatible changes may be made. Backward compatible changes
 * may be added together with the corresponding interface version bump.
 * Backward incompatible changes are done by bumping the version number in
 * the protocol and interface names and resetting the interface version.
 * Once the protocol is to be declared stable, the 'z' prefix and the
 * version number in the protocol and interface names are removed and the
 * interface version number is reset.
 *
 * @section page_ifaces_wlr_gamma_control_unstable_v1 Interfaces
 * - @subpage page_iface_zwlr_gamma_control_manager_v1 - manager to create per-output gamma controls
 * - @subpage page_iface_zwlr_gamma_control_v1 - adjust gamma tables for an output
 * @section page_copyright_wlr_gamma_control_unstable_v1 Copyright
 * <pre>
 *
 * Copyright © 2015 Giulio camuffo
 * Copyright © 2018 Simon Ser
 *
 * Permission to use, copy, modify, distribute, and sell this
 * software and its documentation for any purpose is hereby granted
 * without fee, provided that the above copyright notice appear in
 * all copies and that both that copyright notice and this permission
 * notice appear in supporting documentation, and that the name of
 * the copyright holders not be used in advertising or publicity
 * pertaining to distribution of the software without specific,
 * written prior permission.  The copyright holders make no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied
 * warranty.
 *
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 * THIS SOFTWARE.
 * </pre>
 */
struct wl_output;
struct zwlr_gamma_control_manager_v1;
struct zwlr_gamma_control_v1;

#ifndef ZWLR_GAMMA_CONTROL_MANAGER_V1_INTERFACE
#define ZWLR_GAMMA_CONTROL_MANAGER_V1_INTERFACE
/**
 * @page page_iface_zwlr_gamma_control_manager_v1 zwlr_gamma_control_manager_v1
 * @section page_iface_zwlr_gamma_control_manager_v1_desc Description
 *
 * This interface is a manager that allows creating per-output gamma
 * controls.
 * @section page_iface_zwlr_gamma_control_manager_v1_api API
 * See @ref iface_zwlr_gamma_control_manager_v1.
 */
/**
 * @defgroup iface_zwlr_gamma_control_manager_v1 The zwlr_gamma_control_manager_v1 interface
 *
 * This interface is a manager that allows creating per-output gamma
 * controls.
 */
extern const struct wl_interface zwlr_gamma_control_manager_v1_interface;
#endif
#ifndef ZWLR_GAMMA_CONTROL_V1_INTERFACE
#define ZWLR_GAMMA_CONTROL_V1_INTERFACE
/**
 * @page page_iface_zwlr_gamma_control_v1 zwlr_gamma_control_v1
 * @section page_iface_zwlr_gamma_control_v1_desc Description
 *
 * This interface allows a client to adjust gamma tables for a particular
 * output.
 *
 * The client will receive the gamma size, and will then be able to set gamma
 * tables. At any time the compositor can send a failed event indicating that
 * this object is no longer valid.
 *
 * There must always be at most one gamma control object per output, which
 * has exclusive access to this particular output. When the gamma control
 * object is destroyed, the gamma table is restored to its original value.
 * @section page_iface_zwlr_gamma_control_v1_api API
 * See @ref iface_zwlr_gamma_control_v1.
 */
/**
 * @defgroup iface_zwlr_gamma_control_v1 The zwlr_gamma_control_v1 interface
 *
 * This interface allows a client to adjust gamma tables for a particular
 * output.
 *
 * The client will receive the gamma size, and will then be able to set gamma
 * tables. At any time the compositor can send a failed event indicating that
 * this object is no longer valid.
 *
 * There must always be at most one gamma control object per output, which
 * has exclusive access to this particular output. When the gamma control
 * object is destroyed, the gamma table is restored to its original value.
 */
extern const struct wl_interface zwlr_gamma_control_v1_interface;
#endif

#define ZWLR_GAMMA_CONTROL_MANAGER_V1_GET_GAMMA_CONTROL 0
#define ZWLR_GAMMA_CONTROL_MANAGER_V1_DESTROY 1


/**
 * @ingroup iface_zwlr_gamma_control_manager_v1
 */
#define ZWLR_GAMMA_CONTROL_MANAGER_V1_GET_GAMMA_CONTROL_SINCE_VERSION 1
/**
 * @ingroup iface_zwlr_gamma_control_manager_v1
 */
#define ZWLR_GAMMA_CONTROL_MANAGER_V1_DESTROY_SINCE_VERSION 1

/** @ingroup iface_zwlr_gamma_control_manager_v1 */
static inline void
zwlr_gamma_control_manager_v1_set_user_data(struct zwlr_gamma_control_manager_v1 *zwlr_gamma_control_manager_v1, void *user_data)
{
	wl_proxy_set_user_data((struct wl_proxy *) zwlr_gamma_control_manager_v1, user_data);
}

/** @ingroup iface_zwlr_gamma_control_manager_v1 */
static inline void *
zwlr_gamma_control_manager_v1_get_user_data(struct zwlr_gamma_control_manager_v1 *zwlr_gamma_control_manager_v1)
{
	return wl_proxy_get_user_data((struct wl_proxy *) zwlr_gamma_control_manager_v1);
}

static inline uint32_t
zwlr_gamma_control_manager_v1_get_version(struct zwlr_gamma_control_manager_v1 *zwlr_gamma_control_manager_v1)
{
	return wl_proxy_get_version((struct wl_proxy *) zwlr_gamma_control_manager_v1);
}

/**
 * @ingroup iface_zwlr_gamma_control_manager_v1
 *
 * Create a gamma control that can be used to adjust gamma tables for the
 * provided output.
 */
static inline struct zwlr_gamma_control_v1 *
zwlr_gamma_control_manager_v1_get_gamma_control(struct zwlr_gamma_control_manager_v1 *zwlr_gamma_control_manager_v1, struct wl_output *output)
{
	struct wl_proxy *id;

	id = wl_proxy_marshal_constructor((struct wl_proxy *) zwlr_gamma_control_manager_v1,
			 ZWLR_GAMMA_CONTROL_MANAGER_V1_GET_GAMMA_CONTROL, &zwlr_gamma_control_v1_interface, NULL, output);

	return (struct zwlr_gamma_control_v1 *) id;
}

/**
 * @ingroup iface_zwlr_gamma_control_manager_v1
 *
 * All objects created by the manager will still remain valid, until their
 * appropriate destroy request has been called.
 */
static inline void
zwlr_gamma_control_manager_v1_destroy(struct zwlr_gamma_control_manager_v1 *zwlr_gamma_control_manager_v1)
{
	wl_proxy_marshal((struct wl_proxy *) zwlr_gamma_control_manager_v1,
			 ZWLR_GAMMA_CONTROL_MANAGER_V1_DESTROY);

	wl_proxy_destroy((struct wl_proxy *) zwlr_gamma_control_manager_v1);
}

#ifndef ZWLR_GAMMA_CONTROL_V1_ERROR_ENUM
#define ZWLR_GAMMA_CONTROL_V1_ERROR_ENUM
enum zwlr_gamma_control_v1_error {
	/**
	 * invalid gamma tables
	 */
	ZWLR_GAMMA_CONTROL_V1_ERROR_INVALID_GAMMA = 1,
};
#endif /* ZWLR_GAMMA_CONTROL_V1_ERROR_ENUM */

/**
 * @ingroup iface_zwlr_gamma_control_v1
 * @struct zwlr_gamma_control_v1_listener
 */
struct zwlr_gamma_control_v1_listener {
	/**
	 * size of gamma ramps
	 *
	 * Advertise the size of each gamma ramp.
	 *
	 * This event is sent immediately when the gamma control object is
	 * created.
	 */
	void (*gamma_size)(void *data,
			   struct zwlr_gamma_control_v1 *zwlr_gamma_control_v1,
			   uint32_t size);
	/**
	 * object no longer valid
	 *
	 * This event indicates that the gamma control is no longer
	 * valid. This can happen for a number of reasons, including: - The
	 * output doesn't support gamma tables - Setting the gamma tables
	 * failed - Another client already has exclusive gamma control for
	 * this output - The compositor has transfered gamma control to
	 * another client
	 *
	 * Upon receiving this event, the client should destroy this
	 * object.
	 */
	void (*failed)(void *data,
		       struct zwlr_gamma_control_v1 *zwlr_gamma_control_v1);
};

/**
 * @ingroup iface_zwlr_gamma_control_v1
 */
static inline int
zwlr_gamma_control_v1_add_listener(struct zwlr_gamma_control_v1 *zwlr_gamma_control_v1,
				   const struct zwlr_gamma_control_v1_listener *listener, void *data)
{
	return wl_proxy_add_listener((struct wl_proxy *) zwlr_gamma_control_v1,
				     (void (**)(void)) listener, data);
}

#define ZWLR_GAMMA_CONTROL_V1_SET_GAMMA 0
#define ZWLR_GAMMA_CONTROL_V1_DESTROY 1

/**
 * @ingroup iface_zwlr_gamma_control_v1
 */
#define ZWLR_GAMMA_CONTROL_V1_GAMMA_SIZE_SINCE_VERSION 1
/**
 * @ingroup iface_zwlr_gamma_control_v1
 */
#define ZWLR_GAMMA_CONTROL_V1_FAILED_SINCE_VERSION 1

/**
 * @ingroup iface_zwlr_gamma_control_v1
 */
#define ZWLR_GAMMA_CONTROL_V1_SET_GAMMA_SINCE_VERSION 1
/**
 * @ingroup iface_zwlr_gamma_control_v1
 */
#define ZWLR_GAMMA_CONTROL_V1_DESTROY_SINCE_VERSION 1

/** @ingroup iface_zwlr_gamma_control_v1 */
static inline void
zwlr_gamma_control_v1_set_user_data(struct zwlr_gamma_control_v1 *zwlr_gamma_control_v1, void *user_data)
{
	wl_proxy_set_user_data((struct wl_proxy *) zwlr_gamma_control_v1, user_data);
}

/** @ingroup iface_zwlr_gamma_control_v1 */
static inline void *
zwlr_gamma_control_v1_get_user_data(struct zwlr_gamma_control_v1 *zwlr_gamma_control_v1)
{
	return wl_proxy_get_user_data((struct wl_proxy *) zwlr_gamma_control_v1);
}

static inline uint32_t
zwlr_gamma_control_v1_get_version(struct zwlr_gamma_control_v1 *zwlr_gamma_control_v1)
{
	return wl_proxy_get_version((struct wl_proxy *) zwlr_gamma_control_v1);
}

/**
 * @ingroup iface_zwlr_gamma_control_v1
 *
 * Set the gamma table. The file descriptor can be memory-mapped to provide
 * the raw gamma table, which contains successive gamma ramps for the red,
 * green and blue channels. Each gamma ramp is an array of 16-byte unsigned
 * integers which has the same length as the gamma size.
 *
 * The file descriptor data must have the same length as three times the
 * gamma size.
 */
static inline void
zwlr_gamma_control_v1_set_gamma(struct zwlr_gamma_control_v1 *zwlr_gamma_control_v1, int32_t fd)
{
	wl_proxy_marshal((struct wl_proxy *) zwlr_gamma_control_v1,
			 ZWLR_GAMMA_CONTROL_V1_SET_GAMMA, fd);
}

/**
 * @ingroup iface_zwlr_gamma_control_v1
 *
 * Destroys the gamma control object. If the object is still valid, this
 * restores the original gamma tables.
 */
static inline void
zwlr_gamma_control_v1_destroy(struct zwlr_gamma_control_v1 *zwlr_gamma_control_v1)
{
	wl_proxy_marshal((struct wl_proxy *) zwlr_gamma_control_v1,
			 ZWLR_GAMMA_CONTROL_V1_DESTROY);

	wl_proxy_destroy((struct wl_proxy *) zwlr_gamma_control_v1);
}

#ifdef  __cplusplus
}
#endif

#endif


================================================
FILE: waysct/gamma-control-protocol.h
================================================
/* Generated by wayland-scanner 1.19.0 */

/*
 * Copyright © 2015 Giulio camuffo
 * Copyright © 2018 Simon Ser
 *
 * Permission to use, copy, modify, distribute, and sell this
 * software and its documentation for any purpose is hereby granted
 * without fee, provided that the above copyright notice appear in
 * all copies and that both that copyright notice and this permission
 * notice appear in supporting documentation, and that the name of
 * the copyright holders not be used in advertising or publicity
 * pertaining to distribution of the software without specific,
 * written prior permission.  The copyright holders make no
 * representations about the suitability of this software for any
 * purpose.  It is provided "as is" without express or implied
 * warranty.
 *
 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 * THIS SOFTWARE.
 */

#include <stdlib.h>
#include <stdint.h>
#include "wayland-util.h"

#ifndef __has_attribute
# define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */
#endif

#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
#define WL_PRIVATE __attribute__ ((visibility("hidden")))
#else
#define WL_PRIVATE
#endif

extern const struct wl_interface wl_output_interface;
extern const struct wl_interface zwlr_gamma_control_v1_interface;

static const struct wl_interface *wlr_gamma_control_unstable_v1_types[] = {
	NULL,
	&zwlr_gamma_control_v1_interface,
	&wl_output_interface,
};

static const struct wl_message zwlr_gamma_control_manager_v1_requests[] = {
	{ "get_gamma_control", "no", wlr_gamma_control_unstable_v1_types + 1 },
	{ "destroy", "", wlr_gamma_control_unstable_v1_types + 0 },
};

WL_PRIVATE const struct wl_interface zwlr_gamma_control_manager_v1_interface = {
	"zwlr_gamma_control_manager_v1", 1,
	2, zwlr_gamma_control_manager_v1_requests,
	0, NULL,
};

static const struct wl_message zwlr_gamma_control_v1_requests[] = {
	{ "set_gamma", "h", wlr_gamma_control_unstable_v1_types + 0 },
	{ "destroy", "", wlr_gamma_control_unstable_v1_types + 0 },
};

static const struct wl_message zwlr_gamma_control_v1_events[] = {
	{ "gamma_size", "u", wlr_gamma_control_unstable_v1_types + 0 },
	{ "failed", "", wlr_gamma_control_unstable_v1_types + 0 },
};

WL_PRIVATE const struct wl_interface zwlr_gamma_control_v1_interface = {
	"zwlr_gamma_control_v1", 1,
	2, zwlr_gamma_control_v1_requests,
	2, zwlr_gamma_control_v1_events,
};



================================================
FILE: waysct/gamma-control.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<protocol name="wlr_gamma_control_unstable_v1">
  <copyright>
    Copyright © 2015 Giulio camuffo
    Copyright © 2018 Simon Ser

    Permission to use, copy, modify, distribute, and sell this
    software and its documentation for any purpose is hereby granted
    without fee, provided that the above copyright notice appear in
    all copies and that both that copyright notice and this permission
    notice appear in supporting documentation, and that the name of
    the copyright holders not be used in advertising or publicity
    pertaining to distribution of the software without specific,
    written prior permission.  The copyright holders make no
    representations about the suitability of this software for any
    purpose.  It is provided "as is" without express or implied
    warranty.

    THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
    SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
    FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
    SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
    AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
    ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
    THIS SOFTWARE.
  </copyright>

  <description summary="manage gamma tables of outputs">
    This protocol allows a privileged client to set the gamma tables for
    outputs.

    Warning! The protocol described in this file is experimental and
    backward incompatible changes may be made. Backward compatible changes
    may be added together with the corresponding interface version bump.
    Backward incompatible changes are done by bumping the version number in
    the protocol and interface names and resetting the interface version.
    Once the protocol is to be declared stable, the 'z' prefix and the
    version number in the protocol and interface names are removed and the
    interface version number is reset.
  </description>

  <interface name="zwlr_gamma_control_manager_v1" version="1">
    <description summary="manager to create per-output gamma controls">
      This interface is a manager that allows creating per-output gamma
      controls.
    </description>

    <request name="get_gamma_control">
      <description summary="get a gamma control for an output">
        Create a gamma control that can be used to adjust gamma tables for the
        provided output.
      </description>
      <arg name="id" type="new_id" interface="zwlr_gamma_control_v1"/>
      <arg name="output" type="object" interface="wl_output"/>
    </request>

    <request name="destroy" type="destructor">
      <description summary="destroy the manager">
        All objects created by the manager will still remain valid, until their
        appropriate destroy request has been called.
      </description>
    </request>
  </interface>

  <interface name="zwlr_gamma_control_v1" version="1">
    <description summary="adjust gamma tables for an output">
      This interface allows a client to adjust gamma tables for a particular
      output.

      The client will receive the gamma size, and will then be able to set gamma
      tables. At any time the compositor can send a failed event indicating that
      this object is no longer valid.

      There must always be at most one gamma control object per output, which
      has exclusive access to this particular output. When the gamma control
      object is destroyed, the gamma table is restored to its original value.
    </description>

    <event name="gamma_size">
      <description summary="size of gamma ramps">
        Advertise the size of each gamma ramp.

        This event is sent immediately when the gamma control object is created.
      </description>
      <arg name="size" type="uint"/>
    </event>

    <enum name="error">
      <entry name="invalid_gamma" value="1" summary="invalid gamma tables"/>
    </enum>

    <request name="set_gamma">
      <description summary="set the gamma table">
        Set the gamma table. The file descriptor can be memory-mapped to provide
        the raw gamma table, which contains successive gamma ramps for the red,
        green and blue channels. Each gamma ramp is an array of 16-byte unsigned
        integers which has the same length as the gamma size.

        The file descriptor data must have the same length as three times the
        gamma size.
      </description>
      <arg name="fd" type="fd" summary="gamma table file descriptor"/>
    </request>

    <event name="failed">
      <description summary="object no longer valid">
        This event indicates that the gamma control is no longer valid. This
        can happen for a number of reasons, including:
        - The output doesn't support gamma tables
        - Setting the gamma tables failed
        - Another client already has exclusive gamma control for this output
        - The compositor has transfered gamma control to another client

        Upon receiving this event, the client should destroy this object.
      </description>
    </event>

    <request name="destroy" type="destructor">
      <description summary="destroy this control">
        Destroys the gamma control object. If the object is still valid, this
        restores the original gamma tables.
      </description>
    </request>
  </interface>
</protocol>


================================================
FILE: waysct/gamma-wl.h
================================================
/* gamma-wl.c -- Wayland gamma adjustment header
   This file is part of Redshift.

   Redshift 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.

   Redshift 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 General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with Redshift.  If not, see <http://www.gnu.org/licenses/>.

   Copyright (c) 2015  Giulio Camuffo <giuliocamuffo@gmail.com>
*/

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <alloca.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdint.h>
#include <wayland-client.h>
#include <math.h>

#ifdef ENABLE_NLS
# include <libintl.h>
# define _(s) gettext(s)
#else
# define _(s) s
#endif

#include "os-compatibility.h"
#include "os-compatibility-impl.h"
//#include "colorramp.h"

#include "gamma-control-client-protocol.h"
#include "gamma-control-protocol.h"
#include "orbital-authorizer-client-protocol.h"
#include "orbital-authorizer-protocol.h"

/* Color setting */
typedef struct {
	int temperature;
	float gamma[3];
	float brightness;
} color_setting_t;

/* Whitepoint values for temperatures at 100K intervals.
   These will be interpolated for the actual temperature.
   This table was provided by Ingo Thies, 2013. See
   the file README-colorramp for more information. */
static const float blackbody_color[] = {
	1.00000000,  0.18172716,  0.00000000, /* 1000K */
	1.00000000,  0.25503671,  0.00000000, /* 1100K */
	1.00000000,  0.30942099,  0.00000000, /* 1200K */
	1.00000000,  0.35357379,  0.00000000, /* ...   */
	1.00000000,  0.39091524,  0.00000000,
	1.00000000,  0.42322816,  0.00000000,
	1.00000000,  0.45159884,  0.00000000,
	1.00000000,  0.47675916,  0.00000000,
	1.00000000,  0.49923747,  0.00000000,
	1.00000000,  0.51943421,  0.00000000,
	1.00000000,  0.54360078,  0.08679949,
	1.00000000,  0.56618736,  0.14065513,
	1.00000000,  0.58734976,  0.18362641,
	1.00000000,  0.60724493,  0.22137978,
	1.00000000,  0.62600248,  0.25591950,
	1.00000000,  0.64373109,  0.28819679,
	1.00000000,  0.66052319,  0.31873863,
	1.00000000,  0.67645822,  0.34786758,
	1.00000000,  0.69160518,  0.37579588,
	1.00000000,  0.70602449,  0.40267128,
	1.00000000,  0.71976951,  0.42860152,
	1.00000000,  0.73288760,  0.45366838,
	1.00000000,  0.74542112,  0.47793608,
	1.00000000,  0.75740814,  0.50145662,
	1.00000000,  0.76888303,  0.52427322,
	1.00000000,  0.77987699,  0.54642268,
	1.00000000,  0.79041843,  0.56793692,
	1.00000000,  0.80053332,  0.58884417,
	1.00000000,  0.81024551,  0.60916971,
	1.00000000,  0.81957693,  0.62893653,
	1.00000000,  0.82854786,  0.64816570,
	1.00000000,  0.83717703,  0.66687674,
	1.00000000,  0.84548188,  0.68508786,
	1.00000000,  0.85347859,  0.70281616,
	1.00000000,  0.86118227,  0.72007777,
	1.00000000,  0.86860704,  0.73688797,
	1.00000000,  0.87576611,  0.75326132,
	1.00000000,  0.88267187,  0.76921169,
	1.00000000,  0.88933596,  0.78475236,
	1.00000000,  0.89576933,  0.79989606,
	1.00000000,  0.90198230,  0.81465502,
	1.00000000,  0.90963069,  0.82838210,
	1.00000000,  0.91710889,  0.84190889,
	1.00000000,  0.92441842,  0.85523742,
	1.00000000,  0.93156127,  0.86836903,
	1.00000000,  0.93853986,  0.88130458,
	1.00000000,  0.94535695,  0.89404470,
	1.00000000,  0.95201559,  0.90658983,
	1.00000000,  0.95851906,  0.91894041,
	1.00000000,  0.96487079,  0.93109690,
	1.00000000,  0.97107439,  0.94305985,
	1.00000000,  0.97713351,  0.95482993,
	1.00000000,  0.98305189,  0.96640795,
	1.00000000,  0.98883326,  0.97779486,
	1.00000000,  0.99448139,  0.98899179,
	1.00000000,  1.00000000,  1.00000000, /* 6500K */
	0.98947904,  0.99348723,  1.00000000,
	0.97940448,  0.98722715,  1.00000000,
	0.96975025,  0.98120637,  1.00000000,
	0.96049223,  0.97541240,  1.00000000,
	0.95160805,  0.96983355,  1.00000000,
	0.94303638,  0.96443333,  1.00000000,
	0.93480451,  0.95923080,  1.00000000,
	0.92689056,  0.95421394,  1.00000000,
	0.91927697,  0.94937330,  1.00000000,
	0.91194747,  0.94470005,  1.00000000,
	0.90488690,  0.94018594,  1.00000000,
	0.89808115,  0.93582323,  1.00000000,
	0.89151710,  0.93160469,  1.00000000,
	0.88518247,  0.92752354,  1.00000000,
	0.87906581,  0.92357340,  1.00000000,
	0.87315640,  0.91974827,  1.00000000,
	0.86744421,  0.91604254,  1.00000000,
	0.86191983,  0.91245088,  1.00000000,
	0.85657444,  0.90896831,  1.00000000,
	0.85139976,  0.90559011,  1.00000000,
	0.84638799,  0.90231183,  1.00000000,
	0.84153180,  0.89912926,  1.00000000,
	0.83682430,  0.89603843,  1.00000000,
	0.83225897,  0.89303558,  1.00000000,
	0.82782969,  0.89011714,  1.00000000,
	0.82353066,  0.88727974,  1.00000000,
	0.81935641,  0.88452017,  1.00000000,
	0.81530175,  0.88183541,  1.00000000,
	0.81136180,  0.87922257,  1.00000000,
	0.80753191,  0.87667891,  1.00000000,
	0.80380769,  0.87420182,  1.00000000,
	0.80018497,  0.87178882,  1.00000000,
	0.79665980,  0.86943756,  1.00000000,
	0.79322843,  0.86714579,  1.00000000,
	0.78988728,  0.86491137,  1.00000000, /* 10000K */
	0.78663296,  0.86273225,  1.00000000,
	0.78346225,  0.86060650,  1.00000000,
	0.78037207,  0.85853224,  1.00000000,
	0.77735950,  0.85650771,  1.00000000,
	0.77442176,  0.85453121,  1.00000000,
	0.77155617,  0.85260112,  1.00000000,
	0.76876022,  0.85071588,  1.00000000,
	0.76603147,  0.84887402,  1.00000000,
	0.76336762,  0.84707411,  1.00000000,
	0.76076645,  0.84531479,  1.00000000,
	0.75822586,  0.84359476,  1.00000000,
	0.75574383,  0.84191277,  1.00000000,
	0.75331843,  0.84026762,  1.00000000,
	0.75094780,  0.83865816,  1.00000000,
	0.74863017,  0.83708329,  1.00000000,
	0.74636386,  0.83554194,  1.00000000,
	0.74414722,  0.83403311,  1.00000000,
	0.74197871,  0.83255582,  1.00000000,
	0.73985682,  0.83110912,  1.00000000,
	0.73778012,  0.82969211,  1.00000000,
	0.73574723,  0.82830393,  1.00000000,
	0.73375683,  0.82694373,  1.00000000,
	0.73180765,  0.82561071,  1.00000000,
	0.72989845,  0.82430410,  1.00000000,
	0.72802807,  0.82302316,  1.00000000,
	0.72619537,  0.82176715,  1.00000000,
	0.72439927,  0.82053539,  1.00000000,
	0.72263872,  0.81932722,  1.00000000,
	0.72091270,  0.81814197,  1.00000000,
	0.71922025,  0.81697905,  1.00000000,
	0.71756043,  0.81583783,  1.00000000,
	0.71593234,  0.81471775,  1.00000000,
	0.71433510,  0.81361825,  1.00000000,
	0.71276788,  0.81253878,  1.00000000,
	0.71122987,  0.81147883,  1.00000000,
	0.70972029,  0.81043789,  1.00000000,
	0.70823838,  0.80941546,  1.00000000,
	0.70678342,  0.80841109,  1.00000000,
	0.70535469,  0.80742432,  1.00000000,
	0.70395153,  0.80645469,  1.00000000,
	0.70257327,  0.80550180,  1.00000000,
	0.70121928,  0.80456522,  1.00000000,
	0.69988894,  0.80364455,  1.00000000,
	0.69858167,  0.80273941,  1.00000000,
	0.69729688,  0.80184943,  1.00000000,
	0.69603402,  0.80097423,  1.00000000,
	0.69479255,  0.80011347,  1.00000000,
	0.69357196,  0.79926681,  1.00000000,
	0.69237173,  0.79843391,  1.00000000,
	0.69119138,  0.79761446,  1.00000000, /* 15000K */
	0.69003044,  0.79680814,  1.00000000,
	0.68888844,  0.79601466,  1.00000000,
	0.68776494,  0.79523371,  1.00000000,
	0.68665951,  0.79446502,  1.00000000,
	0.68557173,  0.79370830,  1.00000000,
	0.68450119,  0.79296330,  1.00000000,
	0.68344751,  0.79222975,  1.00000000,
	0.68241029,  0.79150740,  1.00000000,
	0.68138918,  0.79079600,  1.00000000,
	0.68038380,  0.79009531,  1.00000000,
	0.67939381,  0.78940511,  1.00000000,
	0.67841888,  0.78872517,  1.00000000,
	0.67745866,  0.78805526,  1.00000000,
	0.67651284,  0.78739518,  1.00000000,
	0.67558112,  0.78674472,  1.00000000,
	0.67466317,  0.78610368,  1.00000000,
	0.67375872,  0.78547186,  1.00000000,
	0.67286748,  0.78484907,  1.00000000,
	0.67198916,  0.78423512,  1.00000000,
	0.67112350,  0.78362984,  1.00000000,
	0.67027024,  0.78303305,  1.00000000,
	0.66942911,  0.78244457,  1.00000000,
	0.66859988,  0.78186425,  1.00000000,
	0.66778228,  0.78129191,  1.00000000,
	0.66697610,  0.78072740,  1.00000000,
	0.66618110,  0.78017057,  1.00000000,
	0.66539706,  0.77962127,  1.00000000,
	0.66462376,  0.77907934,  1.00000000,
	0.66386098,  0.77854465,  1.00000000,
	0.66310852,  0.77801705,  1.00000000,
	0.66236618,  0.77749642,  1.00000000,
	0.66163375,  0.77698261,  1.00000000,
	0.66091106,  0.77647551,  1.00000000,
	0.66019791,  0.77597498,  1.00000000,
	0.65949412,  0.77548090,  1.00000000,
	0.65879952,  0.77499315,  1.00000000,
	0.65811392,  0.77451161,  1.00000000,
	0.65743716,  0.77403618,  1.00000000,
	0.65676908,  0.77356673,  1.00000000,
	0.65610952,  0.77310316,  1.00000000,
	0.65545831,  0.77264537,  1.00000000,
	0.65481530,  0.77219324,  1.00000000,
	0.65418036,  0.77174669,  1.00000000,
	0.65355332,  0.77130560,  1.00000000,
	0.65293404,  0.77086988,  1.00000000,
	0.65232240,  0.77043944,  1.00000000,
	0.65171824,  0.77001419,  1.00000000,
	0.65112144,  0.76959404,  1.00000000,
	0.65053187,  0.76917889,  1.00000000,
	0.64994941,  0.76876866,  1.00000000, /* 20000K */
	0.64937392,  0.76836326,  1.00000000,
	0.64880528,  0.76796263,  1.00000000,
	0.64824339,  0.76756666,  1.00000000,
	0.64768812,  0.76717529,  1.00000000,
	0.64713935,  0.76678844,  1.00000000,
	0.64659699,  0.76640603,  1.00000000,
	0.64606092,  0.76602798,  1.00000000,
	0.64553103,  0.76565424,  1.00000000,
	0.64500722,  0.76528472,  1.00000000,
	0.64448939,  0.76491935,  1.00000000,
	0.64397745,  0.76455808,  1.00000000,
	0.64347129,  0.76420082,  1.00000000,
	0.64297081,  0.76384753,  1.00000000,
	0.64247594,  0.76349813,  1.00000000,
	0.64198657,  0.76315256,  1.00000000,
	0.64150261,  0.76281076,  1.00000000,
	0.64102399,  0.76247267,  1.00000000,
	0.64055061,  0.76213824,  1.00000000,
	0.64008239,  0.76180740,  1.00000000,
	0.63961926,  0.76148010,  1.00000000,
	0.63916112,  0.76115628,  1.00000000,
	0.63870790,  0.76083590,  1.00000000,
	0.63825953,  0.76051890,  1.00000000,
	0.63781592,  0.76020522,  1.00000000,
	0.63737701,  0.75989482,  1.00000000,
	0.63694273,  0.75958764,  1.00000000,
	0.63651299,  0.75928365,  1.00000000,
	0.63608774,  0.75898278,  1.00000000,
	0.63566691,  0.75868499,  1.00000000,
	0.63525042,  0.75839025,  1.00000000,
	0.63483822,  0.75809849,  1.00000000,
	0.63443023,  0.75780969,  1.00000000,
	0.63402641,  0.75752379,  1.00000000,
	0.63362667,  0.75724075,  1.00000000,
	0.63323097,  0.75696053,  1.00000000,
	0.63283925,  0.75668310,  1.00000000,
	0.63245144,  0.75640840,  1.00000000,
	0.63206749,  0.75613641,  1.00000000,
	0.63168735,  0.75586707,  1.00000000,
	0.63131096,  0.75560036,  1.00000000,
	0.63093826,  0.75533624,  1.00000000,
	0.63056920,  0.75507467,  1.00000000,
	0.63020374,  0.75481562,  1.00000000,
	0.62984181,  0.75455904,  1.00000000,
	0.62948337,  0.75430491,  1.00000000,
	0.62912838,  0.75405319,  1.00000000,
	0.62877678,  0.75380385,  1.00000000,
	0.62842852,  0.75355685,  1.00000000,
	0.62808356,  0.75331217,  1.00000000,
	0.62774186,  0.75306977,  1.00000000, /* 25000K */
	0.62740336,  0.75282962,  1.00000000  /* 25100K */
};


static void
interpolate_color(float a, const float *c1, const float *c2, float *c)
{
	c[0] = (1.0-a)*c1[0] + a*c2[0];
	c[1] = (1.0-a)*c1[1] + a*c2[1];
	c[2] = (1.0-a)*c1[2] + a*c2[2];
}

/* Helper macro used in the fill functions */
#define F(Y, C)  pow((Y) * setting->brightness * \
		     white_point[C], 1.0/setting->gamma[C])

void
colorramp_fill(uint16_t *gamma_r, uint16_t *gamma_g, uint16_t *gamma_b,
	       int size, const color_setting_t *setting)
{
	/* Approximate white point */
	float white_point[3];
	float alpha = (setting->temperature % 100) / 100.0;
	int temp_index = ((setting->temperature - 1000) / 100)*3;
	interpolate_color(alpha, &blackbody_color[temp_index],
			  &blackbody_color[temp_index+3], white_point);

	for (int i = 0; i < size; i++) {
		gamma_r[i] = F((double)gamma_r[i]/(UINT16_MAX+1), 0) *
			(UINT16_MAX+1);
		gamma_g[i] = F((double)gamma_g[i]/(UINT16_MAX+1), 1) *
			(UINT16_MAX+1);
		gamma_b[i] = F((double)gamma_b[i]/(UINT16_MAX+1), 2) *
			(UINT16_MAX+1);
	}
}

typedef struct {
	struct wl_display *display;
	struct wl_registry *registry;
	struct wl_callback *callback;
	uint32_t gamma_control_manager_id;
	struct zwlr_gamma_control_manager_v1 *gamma_control_manager;
	int num_outputs;
	struct output *outputs;
	int authorized;
} wayland_state_t;

struct output {
	uint32_t global_id;
	struct wl_output *output;
	struct zwlr_gamma_control_v1 *gamma_control;
	uint32_t gamma_size;
};

static int
wayland_init(wayland_state_t **state)
{
	/* Initialize state. */
	*state = malloc(sizeof(**state));
	if (*state == NULL) return -1;

	memset(*state, 0, sizeof **state);
	return 0;
}

static void
authorizer_feedback_granted(void *data, struct orbital_authorizer_feedback *feedback)
{
	wayland_state_t *state = data;
	state->authorized = 1;
}

static void
authorizer_feedback_denied(void *data, struct orbital_authorizer_feedback *feedback)
{
	fprintf(stderr, _("Fatal: redshift was not authorized to bind the 'zwlr_gamma_control_manager_v1' interface.\n"));
	exit(EXIT_FAILURE);
}

static const struct orbital_authorizer_feedback_listener authorizer_feedback_listener = {
	authorizer_feedback_granted,
	authorizer_feedback_denied
};

static void
registry_global(void *data, struct wl_registry *registry, uint32_t id, const char *interface, uint32_t version)
{
	wayland_state_t *state = data;

	if (strcmp(interface, "zwlr_gamma_control_manager_v1") == 0) {
		state->gamma_control_manager_id = id;
		state->gamma_control_manager = wl_registry_bind(registry, id, &zwlr_gamma_control_manager_v1_interface, 1);
	} else if (strcmp(interface, "wl_output") == 0) {
		state->num_outputs++;
		if (!(state->outputs = realloc(state->outputs, state->num_outputs * sizeof(struct output)))) {
			fprintf(stderr, _("Failed to allcate memory\n"));
			return;
		}

		struct output *output = &state->outputs[state->num_outputs - 1];
		output->global_id = id;
		output->output = wl_registry_bind(registry, id, &wl_output_interface, 1);
		output->gamma_control = NULL;
	} else if (strcmp(interface, "orbital_authorizer") == 0) {
		struct wl_event_queue *queue = wl_display_create_queue(state->display);

		struct orbital_authorizer *auth = wl_registry_bind(registry, id, &orbital_authorizer_interface, 1u);
		wl_proxy_set_queue((struct wl_proxy *)auth, queue);

		struct orbital_authorizer_feedback *feedback = orbital_authorizer_authorize(auth, "zwlr_gamma_control_manager_v1");
		orbital_authorizer_feedback_add_listener(feedback, &authorizer_feedback_listener, state);

		int ret = 0;
		while (!state->authorized && ret >= 0) {
			ret = wl_display_dispatch_queue(state->display, queue);
		}

		orbital_authorizer_feedback_destroy(feedback);
		orbital_authorizer_destroy(auth);
		wl_event_queue_destroy(queue);
	}
}

static void
registry_global_remove(void *data, struct wl_registry *registry, uint32_t id)
{
	wayland_state_t *state = data;

	if (state->gamma_control_manager_id == id) {
		fprintf(stderr, _("The zwlr_gamma_control_manager_v1 was removed\n"));
		exit(EXIT_FAILURE);
	}

	for (int i = 0; i < state->num_outputs; ++i) {
		struct output *output = &state->outputs[i];
		if (output->global_id == id) {
			if (output->gamma_control) {
				zwlr_gamma_control_v1_destroy(output->gamma_control);
				output->gamma_control = NULL;
			}
			wl_output_destroy(output->output);

			/* If the removed output is not the last one in the array move the last one
			 * in the now empty slot. Then shrink the array */
			if (i < --state->num_outputs) {
				memcpy(output, &state->outputs[state->num_outputs], sizeof(struct output));
			}
			state->outputs = realloc(state->outputs, state->num_outputs * sizeof(struct output));

			return;
		}
	}
}

static const struct wl_registry_listener registry_listener = {
	registry_global,
	registry_global_remove
};

static void
gamma_control_gamma_size(void *data, struct zwlr_gamma_control_v1 *control, uint32_t size)
{
	struct output *output = data;
	output->gamma_size = size;
}

static void
gamma_control_failed(void *data, struct zwlr_gamma_control_v1 *control)
{
}


static const struct zwlr_gamma_control_v1_listener gamma_control_listener = {
	gamma_control_gamma_size,
	gamma_control_failed
};

static int
wayland_start(wayland_state_t *state)
{
	state->display = wl_display_connect(NULL);
	if (!state->display) {
		fputs(_("Could not connect to wayland display, exiting.\n"), stderr);
		return -1;
	}
	state->registry = wl_display_get_registry(state->display);

	wl_registry_add_listener(state->registry, &registry_listener, state);

	wl_display_roundtrip(state->display);
	if (!state->gamma_control_manager) {
		return -1;
	}
	if (state->num_outputs > 0 && !state->outputs) {
		return -1;
	}

	return 0;
}

static void
wayland_restore(wayland_state_t *state)
{
	for (int i = 0; i < state->num_outputs; ++i) {
		struct output *output = &state->outputs[i];
		if (output->gamma_control) {
			zwlr_gamma_control_v1_destroy(output->gamma_control);
			output->gamma_control = NULL;
		}
	}
	wl_display_flush(state->display);
}

static void
wayland_free(wayland_state_t *state)
{
	int ret = 0;
	/* Wait for the sync callback to destroy everything, otherwise
	 * we could destroy the gamma control before gamma has been set */
	while (state->callback && ret >= 0) {
		ret = wl_display_dispatch(state->display);
	}
	if (state->callback) {
		fprintf(stderr, _("Ignoring error on wayland connection while waiting to disconnect: %d\n"), ret);
		wl_callback_destroy(state->callback);
	}

	for (int i = 0; i < state->num_outputs; ++i) {
		struct output *output = &state->outputs[i];
		if (output->gamma_control) {
			zwlr_gamma_control_v1_destroy(output->gamma_control);
			output->gamma_control = NULL;
		}
		wl_output_destroy(output->output);
	}

	if (state->gamma_control_manager) {
		zwlr_gamma_control_manager_v1_destroy(state->gamma_control_manager);
	}
	if (state->registry) {
		wl_registry_destroy(state->registry);
	}
	if (state->display) {
		wl_display_disconnect(state->display);
	}

	free(state);
}

static void
callback_done(void *data, struct wl_callback *cb, uint32_t t)
{
	wayland_state_t *state = data;
	state->callback = NULL;
	wl_callback_destroy(cb);
}

static const struct wl_callback_listener callback_listener = {
	callback_done
};

static int
wayland_set_temperature(wayland_state_t *state, const color_setting_t *setting)
{
	int ret = 0, roundtrip = 0;

	/* We wait for the sync callback to throttle a bit and not send more
	 * requests than the compositor can manage, otherwise we'd get disconnected.
	 * This also allows us to dispatch other incoming events such as
	 * wl_registry.global_remove. */
	while (state->callback && ret >= 0) {
		ret = wl_display_dispatch(state->display);
	}
	if (ret < 0) {
		fprintf(stderr, _("The Wayland connection experienced a fatal error: %d\n"), ret);
		return ret;
	}

	for (int i = 0; i < state->num_outputs; ++i) {
		struct output *output = &state->outputs[i];
		if (!output->gamma_control) {
			output->gamma_control = zwlr_gamma_control_manager_v1_get_gamma_control(state->gamma_control_manager, output->output);
			zwlr_gamma_control_v1_add_listener(output->gamma_control, &gamma_control_listener, output);
			roundtrip = 1;
		}
	}
	if (roundtrip) {
		wl_display_roundtrip(state->display);
	}

	for (int i = 0; i < state->num_outputs; ++i) {
		struct output *output = &state->outputs[i];
		int size = output->gamma_size;
		size_t ramp_bytes = size * sizeof(uint16_t);
		size_t total_bytes = ramp_bytes * 3;

		int fd = os_create_anonymous_file(total_bytes);
		if (fd < 0) {
			perror("os_create_anonymous_file");
			return -1;
		}

		void *ptr = mmap(NULL, total_bytes,
			PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
		if (ptr == MAP_FAILED) {
			perror("mmap");
			close(fd);
			return -1;
		}

		uint16_t *r_gamma = ptr;
		uint16_t *g_gamma = ptr + ramp_bytes;
		uint16_t *b_gamma = ptr + 2 * ramp_bytes;

		/* Initialize gamma ramps to pure state */
		for (int i = 0; i < size; i++) {
			uint16_t value = (double)i / size * (UINT16_MAX+1);
			r_gamma[i] = value;
			g_gamma[i] = value;
			b_gamma[i] = value;
		}

		colorramp_fill(r_gamma, g_gamma, b_gamma, size, setting);
		if (munmap(ptr, total_bytes) == -1) {
			perror("munmap");
			close(fd);
			return -1;
		}

		zwlr_gamma_control_v1_set_gamma(output->gamma_control, fd);
		close(fd);
	}

	state->callback = wl_display_sync(state->display);
	wl_callback_add_listener(state->callback, &callback_listener, state);
	wl_display_flush(state->display);

	return 0;
}


================================================
FILE: waysct/orbital-authorizer-client-protocol.h
================================================
/* Generated by wayland-scanner 1.19.0 */

#ifndef ORBITAL_AUTHORIZER_CLIENT_PROTOCOL_H
#define ORBITAL_AUTHORIZER_CLIENT_PROTOCOL_H

#include <stdint.h>
#include <stddef.h>
#include "wayland-client.h"

#ifdef  __cplusplus
extern "C" {
#endif

/**
 * @page page_orbital_authorizer The orbital_authorizer protocol
 * @section page_ifaces_orbital_authorizer Interfaces
 * - @subpage page_iface_orbital_authorizer - authorize clients to use certain interfaces
 * - @subpage page_iface_orbital_authorizer_feedback - feedback for an authorization request
 */
struct orbital_authorizer;
struct orbital_authorizer_feedback;

#ifndef ORBITAL_AUTHORIZER_INTERFACE
#define ORBITAL_AUTHORIZER_INTERFACE
/**
 * @page page_iface_orbital_authorizer orbital_authorizer
 * @section page_iface_orbital_authorizer_desc Description
 *
 * The orbital_authorizer global interface allows clients to
 * ask the compositor the authorization to bind certain restricted
 * global interfaces.
 * Any client that aims to bind restricted interfaces should first
 * request the authorization by using this interface. Failing to do
 * so will result in the compositor sending a protocol error to the
 * client when it binds the restricted interface.
 *
 * The list of restricted interfaces is compositor dependant, but must
 * not include the core interfaces defined in wayland.xml.
 * @section page_iface_orbital_authorizer_api API
 * See @ref iface_orbital_authorizer.
 */
/**
 * @defgroup iface_orbital_authorizer The orbital_authorizer interface
 *
 * The orbital_authorizer global interface allows clients to
 * ask the compositor the authorization to bind certain restricted
 * global interfaces.
 * Any client that aims to bind restricted interfaces should first
 * request the authorization by using this interface. Failing to do
 * so will result in the compositor sending a protocol error to the
 * client when it binds the restricted interface.
 *
 * The list of restricted interfaces is compositor dependant, but must
 * not include the core interfaces defined in wayland.xml.
 */
extern const struct wl_interface orbital_authorizer_interface;
#endif
#ifndef ORBITAL_AUTHORIZER_FEEDBACK_INTERFACE
#define ORBITAL_AUTHORIZER_FEEDBACK_INTERFACE
/**
 * @page page_iface_orbital_authorizer_feedback orbital_authorizer_feedback
 * @section page_iface_orbital_authorizer_feedback_desc Description
 *
 * The orbital_authorizer_feedback interface is used by requesting
 * an authorization with the orbital_authorizer.authorize request.
 * The compositor will send either the granted or denied event based
 * on the system and user configuration. How the authorization process
 * works is compositor specific, but a compositor is allowed to ask
 * for user input, so the response for an authorization request may
 * come after some time.
 * @section page_iface_orbital_authorizer_feedback_api API
 * See @ref iface_orbital_authorizer_feedback.
 */
/**
 * @defgroup iface_orbital_authorizer_feedback The orbital_authorizer_feedback interface
 *
 * The orbital_authorizer_feedback interface is used by requesting
 * an authorization with the orbital_authorizer.authorize request.
 * The compositor will send either the granted or denied event based
 * on the system and user configuration. How the authorization process
 * works is compositor specific, but a compositor is allowed to ask
 * for user input, so the response for an authorization request may
 * come after some time.
 */
extern const struct wl_interface orbital_authorizer_feedback_interface;
#endif

#define ORBITAL_AUTHORIZER_DESTROY 0
#define ORBITAL_AUTHORIZER_AUTHORIZE 1


/**
 * @ingroup iface_orbital_authorizer
 */
#define ORBITAL_AUTHORIZER_DESTROY_SINCE_VERSION 1
/**
 * @ingroup iface_orbital_authorizer
 */
#define ORBITAL_AUTHORIZER_AUTHORIZE_SINCE_VERSION 1

/** @ingroup iface_orbital_authorizer */
static inline void
orbital_authorizer_set_user_data(struct orbital_authorizer *orbital_authorizer, void *user_data)
{
	wl_proxy_set_user_data((struct wl_proxy *) orbital_authorizer, user_data);
}

/** @ingroup iface_orbital_authorizer */
static inline void *
orbital_authorizer_get_user_data(struct orbital_authorizer *orbital_authorizer)
{
	return wl_proxy_get_user_data((struct wl_proxy *) orbital_authorizer);
}

static inline uint32_t
orbital_authorizer_get_version(struct orbital_authorizer *orbital_authorizer)
{
	return wl_proxy_get_version((struct wl_proxy *) orbital_authorizer);
}

/**
 * @ingroup iface_orbital_authorizer
 */
static inline void
orbital_authorizer_destroy(struct orbital_authorizer *orbital_authorizer)
{
	wl_proxy_marshal((struct wl_proxy *) orbital_authorizer,
			 ORBITAL_AUTHORIZER_DESTROY);

	wl_proxy_destroy((struct wl_proxy *) orbital_authorizer);
}

/**
 * @ingroup iface_orbital_authorizer
 *
 * The authorize request allows the client to ask the compositor the
 * authorization to bind a restricted global interface. The newly
 * created orbital_authorizer_feedback will be invalid after the
 * compositor send either the granted or denied event so the client
 * must destroy it immediately after.
 */
static inline struct orbital_authorizer_feedback *
orbital_authorizer_authorize(struct orbital_authorizer *orbital_authorizer, const char *global)
{
	struct wl_proxy *id;

	id = wl_proxy_marshal_constructor((struct wl_proxy *) orbital_authorizer,
			 ORBITAL_AUTHORIZER_AUTHORIZE, &orbital_authorizer_feedback_interface, NULL, global);

	return (struct orbital_authorizer_feedback *) id;
}

/**
 * @ingroup iface_orbital_authorizer_feedback
 * @struct orbital_authorizer_feedback_listener
 */
struct orbital_authorizer_feedback_listener {
	/**
	 * the authorization was granted
	 *
	 * The authorization was granted. The client can now bind the
	 * restricted interface.
	 */
	void (*granted)(void *data,
			struct orbital_authorizer_feedback *orbital_authorizer_feedback);
	/**
	 * the authorization was denied
	 *
	 * The authorization was denied. The client is not allowed to
	 * bind the restricted interface and trying to do so will trigger a
	 * protocol error killing the client.
	 */
	void (*denied)(void *data,
		       struct orbital_authorizer_feedback *orbital_authorizer_feedback);
};

/**
 * @ingroup iface_orbital_authorizer_feedback
 */
static inline int
orbital_authorizer_feedback_add_listener(struct orbital_authorizer_feedback *orbital_authorizer_feedback,
					 const struct orbital_authorizer_feedback_listener *listener, void *data)
{
	return wl_proxy_add_listener((struct wl_proxy *) orbital_authorizer_feedback,
				     (void (**)(void)) listener, data);
}

/**
 * @ingroup iface_orbital_authorizer_feedback
 */
#define ORBITAL_AUTHORIZER_FEEDBACK_GRANTED_SINCE_VERSION 1
/**
 * @ingroup iface_orbital_authorizer_feedback
 */
#define ORBITAL_AUTHORIZER_FEEDBACK_DENIED_SINCE_VERSION 1


/** @ingroup iface_orbital_authorizer_feedback */
static inline void
orbital_authorizer_feedback_set_user_data(struct orbital_authorizer_feedback *orbital_authorizer_feedback, void *user_data)
{
	wl_proxy_set_user_data((struct wl_proxy *) orbital_authorizer_feedback, user_data);
}

/** @ingroup iface_orbital_authorizer_feedback */
static inline void *
orbital_authorizer_feedback_get_user_data(struct orbital_authorizer_feedback *orbital_authorizer_feedback)
{
	return wl_proxy_get_user_data((struct wl_proxy *) orbital_authorizer_feedback);
}

static inline uint32_t
orbital_authorizer_feedback_get_version(struct orbital_authorizer_feedback *orbital_authorizer_feedback)
{
	return wl_proxy_get_version((struct wl_proxy *) orbital_authorizer_feedback);
}

/** @ingroup iface_orbital_authorizer_feedback */
static inline void
orbital_authorizer_feedback_destroy(struct orbital_authorizer_feedback *orbital_authorizer_feedback)
{
	wl_proxy_destroy((struct wl_proxy *) orbital_authorizer_feedback);
}

#ifdef  __cplusplus
}
#endif

#endif


================================================
FILE: waysct/orbital-authorizer-protocol.h
================================================
/* Generated by wayland-scanner 1.19.0 */

#include <stdlib.h>
#include <stdint.h>
#include "wayland-util.h"

#ifndef __has_attribute
# define __has_attribute(x) 0  /* Compatibility with non-clang compilers. */
#endif

#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
#define WL_PRIVATE __attribute__ ((visibility("hidden")))
#else
#define WL_PRIVATE
#endif

extern const struct wl_interface orbital_authorizer_feedback_interface;

static const struct wl_interface *orbital_authorizer_types[] = {
	&orbital_authorizer_feedback_interface,
	NULL,
};

static const struct wl_message orbital_authorizer_requests[] = {
	{ "destroy", "", orbital_authorizer_types + 0 },
	{ "authorize", "ns", orbital_authorizer_types + 0 },
};

WL_PRIVATE const struct wl_interface orbital_authorizer_interface = {
	"orbital_authorizer", 1,
	2, orbital_authorizer_requests,
	0, NULL,
};

static const struct wl_message orbital_authorizer_feedback_events[] = {
	{ "granted", "", orbital_authorizer_types + 0 },
	{ "denied", "", orbital_authorizer_types + 0 },
};

WL_PRIVATE const struct wl_interface orbital_authorizer_feedback_interface = {
	"orbital_authorizer_feedback", 1,
	0, NULL,
	2, orbital_authorizer_feedback_events,
};



================================================
FILE: waysct/orbital-authorizer.xml
================================================
<protocol name="orbital_authorizer">

    <interface name="orbital_authorizer" version="1">
        <description summary="authorize clients to use certain interfaces">
            The orbital_authorizer global interface allows clients to
            ask the compositor the authorization to bind certain restricted
            global interfaces.
            Any client that aims to bind restricted interfaces should first
            request the authorization by using this interface. Failing to do
            so will result in the compositor sending a protocol error to the
            client when it binds the restricted interface.

            The list of restricted interfaces is compositor dependant, but must
            not include the core interfaces defined in wayland.xml.
        </description>

        <request name="destroy" type="destructor">
            <description summary="destroy this orbital_authorizer object"/>
        </request>

        <request name="authorize">
            <description summary="authorize a global interface">
                The authorize request allows the client to ask the compositor the
                authorization to bind a restricted global interface. The newly
                created orbital_authorizer_feedback will be invalid after the
                compositor send either the granted or denied event so the client
                must destroy it immediately after.
            </description>
            <arg name="id" type="new_id" interface="orbital_authorizer_feedback" summary="the new feedback object"/>
            <arg name="global" type="string" summary="the global interface the client wants to bind"/>
        </request>
    </interface>

    <interface name="orbital_authorizer_feedback" version="1">
        <description summary="feedback for an authorization request">
            The orbital_authorizer_feedback interface is used by requesting
            an authorization with the orbital_authorizer.authorize request.
            The compositor will send either the granted or denied event based
            on the system and user configuration. How the authorization process
            works is compositor specific, but a compositor is allowed to ask
            for user input, so the response for an authorization request may
            come after some time.
        </description>

        <event name="granted">
            <description summary="the authorization was granted">
                The authorization was granted. The client can now bind the restricted
                interface.
            </description>
        </event>

        <event name="denied">
            <description summary="the authorization was denied">
                The authorization was denied. The client is not allowed to bind the
                restricted interface and trying to do so will trigger a protocol
                error killing the client.
            </description>
        </event>
    </interface>

</protocol>


================================================
FILE: waysct/os-compatibility-impl.h
================================================
/*
 * Copyright © 2012 Collabora, Ltd.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice (including the
 * next paragraph) shall be included in all copies or substantial
 * portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#define _POSIX_C_SOURCE 200809L
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include "os-compatibility.h"

int os_fd_set_cloexec(int fd) {
	if (fd == -1) {
		return -1;
	}

	long flags = fcntl(fd, F_GETFD);
	if (flags == -1) {
		return -1;
	}

	if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) {
		return -1;
	}

	return 0;
}

int set_cloexec_or_close(int fd) {
	if (os_fd_set_cloexec(fd) != 0) {
		close(fd);
		return -1;
	}
	return fd;
}

int create_tmpfile_cloexec(char *tmpname) {
	int fd;
	mode_t prev_umask = umask(0066);
#ifdef HAVE_MKOSTEMP
	fd = mkostemp(tmpname, O_CLOEXEC);
	if (fd >= 0) {
		unlink(tmpname);
	}
#else
	fd = mkstemp(tmpname);
	if (fd >= 0) {
		fd = set_cloexec_or_close(fd);
		unlink(tmpname);
	}
#endif
	umask(prev_umask);

	return fd;
}

/*
 * Create a new, unique, anonymous file of the given size, and
 * return the file descriptor for it. The file descriptor is set
 * CLOEXEC. The file is immediately suitable for mmap()'ing
 * the given size at offset zero.
 *
 * The file should not have a permanent backing store like a disk,
 * but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
 *
 * The file name is deleted from the file system.
 *
 * The file is suitable for buffer sharing between processes by
 * transmitting the file descriptor over Unix sockets using the
 * SCM_RIGHTS methods.
 *
 * If the C library implements posix_fallocate(), it is used to
 * guarantee that disk space is available for the file at the
 * given size. If disk space is insufficient, errno is set to ENOSPC.
 * If posix_fallocate() is not supported, program may receive
 * SIGBUS on accessing mmap()'ed file contents instead.
 */
int os_create_anonymous_file(off_t size) {
	static const char template[] = "/redshift-shared-XXXXXX";

	const char *path = getenv("XDG_RUNTIME_DIR");
	if (!path) {
		errno = ENOENT;
		return -1;
	}

	char *name = malloc(strlen(path) + sizeof(template));
	if (!name) {
		return -1;
	}

	strcpy(name, path);
	strcat(name, template);

	int fd = create_tmpfile_cloexec(name);
	free(name);
	if (fd < 0) {
		return -1;
	}

#ifdef WLR_HAS_POSIX_FALLOCATE
	int ret;
	do {
		ret = posix_fallocate(fd, 0, size);
	} while (ret == EINTR);
	if (ret != 0) {
		close(fd);
		errno = ret;
		return -1;
	}
#else
	int ret;
	do {
		ret = ftruncate(fd, size);
	} while (ret < 0 && errno == EINTR);
	if (ret < 0) {
		close(fd);
		return -1;
	}
#endif

	return fd;
}


================================================
FILE: waysct/os-compatibility.h
================================================
#ifndef UTIL_OS_COMPATIBILITY_H
#define UTIL_OS_COMPATIBILITY_H

int os_fd_set_cloexec(int fd);
int set_cloexec_or_close(int fd);
int create_tmpfile_cloexec(char *tmpname);
int os_create_anonymous_file(off_t size);

#endif


================================================
FILE: waysct/waysct.go
================================================
// waysct is a set color temp implementation for Wayland.
// Many of these files are taken from
// https://github.com/minus7/redshift/commit/7da875d34854a6a34612d5ce4bd8718c32bec804
// see Redshift for the GPL license.
package waysct

//go:generate wayland-scanner private-code orbital-authorizer.xml orbital-authorizer-protocol.h
//go:generate wayland-scanner client-header orbital-authorizer.xml orbital-authorizer-client-protocol.h
//go:generate wayland-scanner private-code gamma-control.xml gamma-control-protocol.h
//go:generate wayland-scanner client-header gamma-control.xml gamma-control-client-protocol.h

// #cgo LDFLAGS: -lm -lwayland-client
// #include "gamma-wl.h"
import "C"
import (
	"github.com/pkg/errors"
)

type Manager struct {
	state *C.wayland_state_t
}

func StartManager() (*Manager, error) {
	m := Manager{}
	if errno := C.wayland_init(&m.state); errno != 0 {
		return nil, errors.Errorf("wayland_init: errno %d", errno)
	}
	if errno := C.wayland_start(m.state); errno != 0 {
		return nil, errors.Errorf("wayland_start: errno %d", errno)
	}
	return &m, nil
}

func (m *Manager) Close() {
	C.wayland_free(m.state)
	m.state = nil
}

func (m *Manager) SetColorTemp(temp int) error {
	var setting C.color_setting_t
	setting.brightness = 1.0
	setting.gamma[0] = 1.0
	setting.gamma[1] = 1.0
	setting.gamma[2] = 1.0
	setting.temperature = C.int(temp)
	if errno := C.wayland_set_temperature(m.state, &setting); errno != 0 {
		return errors.Errorf("wayland_set_temperature: errno %d", errno)
	}
	return nil
}
Download .txt
gitextract_ec4q16gx/

├── .travis.yml
├── Dockerfile
├── LICENSE
├── README.md
├── cmd/
│   ├── sct/
│   │   └── sct.go
│   └── waysct/
│       └── waysct.go
├── geoip/
│   ├── geoip.go
│   └── geoip_test.go
├── go.mod
├── go.sum
├── sct.go
├── sct_nix.go
├── sct_windows.go
├── sctcli/
│   ├── sctcli.go
│   └── sctcli_test.go
├── test.sh
└── waysct/
    ├── gamma-control-client-protocol.h
    ├── gamma-control-protocol.h
    ├── gamma-control.xml
    ├── gamma-wl.h
    ├── orbital-authorizer-client-protocol.h
    ├── orbital-authorizer-protocol.h
    ├── orbital-authorizer.xml
    ├── os-compatibility-impl.h
    ├── os-compatibility.h
    └── waysct.go
Download .txt
SYMBOL INDEX (107 symbols across 16 files)

FILE: cmd/sct/sct.go
  function main (line 8) | func main() {

FILE: cmd/waysct/waysct.go
  function main (line 11) | func main() {

FILE: geoip/geoip.go
  type GeoIP (line 10) | type GeoIP struct
  function LookupIP (line 17) | func LookupIP(address string) (*GeoIP, error) {

FILE: geoip/geoip_test.go
  function TestLookupIP (line 5) | func TestLookupIP(t *testing.T) {

FILE: sct.go
  type color (line 5) | type color struct
  function SetColorTemp (line 34) | func SetColorTemp(temp int) {
  function setColorTemp (line 42) | func setColorTemp(temp int) {

FILE: sct_nix.go
  function setColorGamma (line 40) | func setColorGamma(gammar, gammag, gammab float64) {

FILE: sct_windows.go
  function setColorGamma (line 9) | func setColorGamma(gammar, gammag, gammab float64) {

FILE: sctcli/sctcli.go
  function Main (line 27) | func Main(setColorTemp func(temp int) error) {
  type SCTCLI (line 36) | type SCTCLI struct
    method monitorGeo (line 40) | func (c SCTCLI) monitorGeo() error {
    method interpolateColorTemp (line 77) | func (c SCTCLI) interpolateColorTemp(new int) error {
    method monitorTime (line 119) | func (c SCTCLI) monitorTime() error {
    method Run (line 154) | func (c SCTCLI) Run() error {
  function tempFile (line 99) | func tempFile() string {
  function saveCurrentColorTemp (line 104) | func saveCurrentColorTemp(temp int) error {
  function getCurrentColorTemp (line 108) | func getCurrentColorTemp() (int, error) {

FILE: sctcli/sctcli_test.go
  function setDisplay (line 9) | func setDisplay(val string) func() {
  function TestGetCurrentColorTemp (line 17) | func TestGetCurrentColorTemp(t *testing.T) {
  function TestInterpolate (line 42) | func TestInterpolate(t *testing.T) {

FILE: waysct/gamma-control-client-protocol.h
  type wl_output (line 63) | struct wl_output
  type zwlr_gamma_control_manager_v1 (line 64) | struct zwlr_gamma_control_manager_v1
  type zwlr_gamma_control_v1 (line 65) | struct zwlr_gamma_control_v1
  type wl_interface (line 84) | struct wl_interface
  type wl_interface (line 119) | struct wl_interface
  function zwlr_gamma_control_manager_v1_set_user_data (line 136) | static inline void
  type zwlr_gamma_control_manager_v1 (line 144) | struct zwlr_gamma_control_manager_v1
  type wl_proxy (line 146) | struct wl_proxy
  function zwlr_gamma_control_manager_v1_get_version (line 149) | static inline uint32_t
  type zwlr_gamma_control_v1 (line 161) | struct zwlr_gamma_control_v1
  type zwlr_gamma_control_manager_v1 (line 162) | struct zwlr_gamma_control_manager_v1
  type wl_output (line 162) | struct wl_output
  type wl_proxy (line 164) | struct wl_proxy
  type wl_proxy (line 166) | struct wl_proxy
  type zwlr_gamma_control_v1 (line 169) | struct zwlr_gamma_control_v1
  function zwlr_gamma_control_manager_v1_destroy (line 178) | static inline void
  type zwlr_gamma_control_v1_error (line 189) | enum zwlr_gamma_control_v1_error {
  type zwlr_gamma_control_v1_listener (line 201) | struct zwlr_gamma_control_v1_listener {
  function zwlr_gamma_control_v1_add_listener (line 233) | static inline int
  function zwlr_gamma_control_v1_set_user_data (line 263) | static inline void
  type zwlr_gamma_control_v1 (line 271) | struct zwlr_gamma_control_v1
  type wl_proxy (line 273) | struct wl_proxy
  function zwlr_gamma_control_v1_get_version (line 276) | static inline uint32_t
  function zwlr_gamma_control_v1_set_gamma (line 293) | static inline void
  function zwlr_gamma_control_v1_destroy (line 306) | static inline void

FILE: waysct/gamma-control-protocol.h
  type wl_interface (line 43) | struct wl_interface
  type wl_interface (line 44) | struct wl_interface
  type wl_interface (line 46) | struct wl_interface
  type wl_message (line 52) | struct wl_message
  type wl_message (line 63) | struct wl_message
  type wl_message (line 68) | struct wl_message

FILE: waysct/gamma-wl.h
  type color_setting_t (line 51) | typedef struct {
  function interpolate_color (line 307) | static void
  function colorramp_fill (line 319) | void
  type wayland_state_t (line 340) | typedef struct {
  type output (line 351) | struct output {
  function wayland_init (line 358) | static int
  function authorizer_feedback_granted (line 369) | static void
  function authorizer_feedback_denied (line 376) | static void
  type orbital_authorizer_feedback_listener (line 383) | struct orbital_authorizer_feedback_listener
  function registry_global (line 388) | static void
  function registry_global_remove (line 427) | static void
  type wl_registry_listener (line 458) | struct wl_registry_listener
  function gamma_control_gamma_size (line 463) | static void
  function gamma_control_failed (line 470) | static void
  type zwlr_gamma_control_v1_listener (line 476) | struct zwlr_gamma_control_v1_listener
  function wayland_start (line 481) | static int
  function wayland_restore (line 504) | static void
  function wayland_free (line 517) | static void
  function callback_done (line 553) | static void
  type wl_callback_listener (line 561) | struct wl_callback_listener
  function wayland_set_temperature (line 565) | static int

FILE: waysct/orbital-authorizer-client-protocol.h
  type orbital_authorizer (line 20) | struct orbital_authorizer
  type orbital_authorizer_feedback (line 21) | struct orbital_authorizer_feedback
  type wl_interface (line 56) | struct wl_interface
  type wl_interface (line 85) | struct wl_interface
  function orbital_authorizer_set_user_data (line 102) | static inline void
  type orbital_authorizer (line 110) | struct orbital_authorizer
  type wl_proxy (line 112) | struct wl_proxy
  function orbital_authorizer_get_version (line 115) | static inline uint32_t
  function orbital_authorizer_destroy (line 124) | static inline void
  type orbital_authorizer_feedback (line 142) | struct orbital_authorizer_feedback
  type orbital_authorizer (line 143) | struct orbital_authorizer
  type wl_proxy (line 145) | struct wl_proxy
  type wl_proxy (line 147) | struct wl_proxy
  type orbital_authorizer_feedback (line 150) | struct orbital_authorizer_feedback
  type orbital_authorizer_feedback_listener (line 157) | struct orbital_authorizer_feedback_listener {
  function orbital_authorizer_feedback_add_listener (line 180) | static inline int
  function orbital_authorizer_feedback_set_user_data (line 199) | static inline void
  type orbital_authorizer_feedback (line 207) | struct orbital_authorizer_feedback
  type wl_proxy (line 209) | struct wl_proxy
  function orbital_authorizer_feedback_get_version (line 212) | static inline uint32_t
  function orbital_authorizer_feedback_destroy (line 219) | static inline void

FILE: waysct/orbital-authorizer-protocol.h
  type wl_interface (line 17) | struct wl_interface
  type wl_interface (line 19) | struct wl_interface
  type wl_message (line 24) | struct wl_message
  type wl_message (line 35) | struct wl_message

FILE: waysct/os-compatibility-impl.h
  function os_fd_set_cloexec (line 37) | int os_fd_set_cloexec(int fd) {
  function set_cloexec_or_close (line 54) | int set_cloexec_or_close(int fd) {
  function create_tmpfile_cloexec (line 62) | int create_tmpfile_cloexec(char *tmpname) {
  function os_create_anonymous_file (line 103) | int os_create_anonymous_file(off_t size) {

FILE: waysct/waysct.go
  type Manager (line 19) | type Manager struct
    method Close (line 34) | func (m *Manager) Close() {
    method SetColorTemp (line 39) | func (m *Manager) SetColorTemp(temp int) error {
  function StartManager (line 23) | func StartManager() (*Manager, error) {
Condensed preview — 26 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (79K chars).
[
  {
    "path": ".travis.yml",
    "chars": 204,
    "preview": "sudo: required\n\nservices:\n  - docker\n\nlanguage: go\ngo: 1.10.x\n\nscript:\n  - docker build -t sct .\n  - docker run --rm -it"
  },
  {
    "path": "Dockerfile",
    "chars": 193,
    "preview": "FROM golang:1.10\n\nRUN apt-get update && apt-get install -y curl xvfb xorg-dev libglu1-mesa-dev\n\nWORKDIR /go/src/github.c"
  },
  {
    "path": "LICENSE",
    "chars": 1056,
    "preview": "Copyright (C) 2015 Tristan Rice\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this so"
  },
  {
    "path": "README.md",
    "chars": 1937,
    "preview": "# go-sct [![GoDoc](https://godoc.org/github.com/d4l3k/go-sct?status.svg)](https://godoc.org/github.com/d4l3k/go-sct)\n\nA "
  },
  {
    "path": "cmd/sct/sct.go",
    "chars": 181,
    "preview": "package main\n\nimport (\n\t\"github.com/d4l3k/go-sct\"\n\t\"github.com/d4l3k/go-sct/sctcli\"\n)\n\nfunc main() {\n\tsctcli.Main(func(t"
  },
  {
    "path": "cmd/waysct/waysct.go",
    "chars": 293,
    "preview": "// waysct is a set color temp utility for Wayland.\npackage main\n\nimport (\n\t\"log\"\n\n\t\"github.com/d4l3k/go-sct/sctcli\"\n\t\"gi"
  },
  {
    "path": "geoip/geoip.go",
    "chars": 695,
    "preview": "// geoip returns the lat/lng of the target IP address (or current machine)\npackage geoip\n\nimport (\n\t\"encoding/json\"\n\t\"fm"
  },
  {
    "path": "geoip/geoip_test.go",
    "chars": 290,
    "preview": "package geoip\n\nimport \"testing\"\n\nfunc TestLookupIP(t *testing.T) {\n\tgeo, err := LookupIP(\"\")\n\tif err != nil {\n\t\tt.Fatal("
  },
  {
    "path": "go.mod",
    "chars": 149,
    "preview": "module github.com/d4l3k/go-sct\n\ngo 1.16\n\nrequire (\n\tgithub.com/cpucycle/astrotime v0.0.0-20120927164819-9c7d514efdb5\n\tgi"
  },
  {
    "path": "go.sum",
    "chars": 394,
    "preview": "github.com/cpucycle/astrotime v0.0.0-20120927164819-9c7d514efdb5 h1:Z6YGTs9TwkwIVCltpgUNFa+L5SAyGfIL9gH0RB7yDgw=\ngithub."
  },
  {
    "path": "sct.go",
    "chars": 1626,
    "preview": "package sct\n\nimport \"runtime\"\n\ntype color struct {\n\tr, g, b float64\n}\n\n/* cribbed from redshift, but truncated with 500K"
  },
  {
    "path": "sct_nix.go",
    "chars": 1952,
    "preview": "// +build linux freebsd openbsd\n\npackage sct\n\n// #cgo CFLAGS: -I/usr/X11R6/include -I/usr/local/include\n// #cgo LDFLAGS:"
  },
  {
    "path": "sct_windows.go",
    "chars": 704,
    "preview": "package sct\n\nimport (\n\t\"syscall\"\n\t\"unsafe\"\n)\n\n// setColorGamma changes the device gamma curve colors to reflect the spec"
  },
  {
    "path": "sctcli/sctcli.go",
    "chars": 5459,
    "preview": "package sctcli\n\nimport (\n\t\"flag\"\n\t\"io/ioutil\"\n\t\"log\"\n\t\"os\"\n\t\"os/exec\"\n\t\"path/filepath\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n\n\t\""
  },
  {
    "path": "sctcli/sctcli_test.go",
    "chars": 1094,
    "preview": "package sctcli\n\nimport (\n\t\"os\"\n\t\"testing\"\n\t\"time\"\n)\n\nfunc setDisplay(val string) func() {\n\told := os.Getenv(\"DISPLAY\")\n\t"
  },
  {
    "path": "test.sh",
    "chars": 39,
    "preview": "#!/bin/bash\n\nxvfb-run go test -v ./...\n"
  },
  {
    "path": "waysct/gamma-control-client-protocol.h",
    "chars": 11050,
    "preview": "/* Generated by wayland-scanner 1.19.0 */\n\n#ifndef WLR_GAMMA_CONTROL_UNSTABLE_V1_CLIENT_PROTOCOL_H\n#define WLR_GAMMA_CON"
  },
  {
    "path": "waysct/gamma-control-protocol.h",
    "chars": 2836,
    "preview": "/* Generated by wayland-scanner 1.19.0 */\n\n/*\n * Copyright © 2015 Giulio camuffo\n * Copyright © 2018 Simon Ser\n *\n * Per"
  },
  {
    "path": "waysct/gamma-control.xml",
    "chars": 5468,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<protocol name=\"wlr_gamma_control_unstable_v1\">\n  <copyright>\n    Copyright © 201"
  },
  {
    "path": "waysct/gamma-wl.h",
    "chars": 20793,
    "preview": "/* gamma-wl.c -- Wayland gamma adjustment header\n   This file is part of Redshift.\n\n   Redshift is free software: you ca"
  },
  {
    "path": "waysct/orbital-authorizer-client-protocol.h",
    "chars": 7841,
    "preview": "/* Generated by wayland-scanner 1.19.0 */\n\n#ifndef ORBITAL_AUTHORIZER_CLIENT_PROTOCOL_H\n#define ORBITAL_AUTHORIZER_CLIEN"
  },
  {
    "path": "waysct/orbital-authorizer-protocol.h",
    "chars": 1231,
    "preview": "/* Generated by wayland-scanner 1.19.0 */\n\n#include <stdlib.h>\n#include <stdint.h>\n#include \"wayland-util.h\"\n\n#ifndef __"
  },
  {
    "path": "waysct/orbital-authorizer.xml",
    "chars": 2995,
    "preview": "<protocol name=\"orbital_authorizer\">\n\n    <interface name=\"orbital_authorizer\" version=\"1\">\n        <description summary"
  },
  {
    "path": "waysct/os-compatibility-impl.h",
    "chars": 3688,
    "preview": "/*\n * Copyright © 2012 Collabora, Ltd.\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a "
  },
  {
    "path": "waysct/os-compatibility.h",
    "chars": 223,
    "preview": "#ifndef UTIL_OS_COMPATIBILITY_H\n#define UTIL_OS_COMPATIBILITY_H\n\nint os_fd_set_cloexec(int fd);\nint set_cloexec_or_close"
  },
  {
    "path": "waysct/waysct.go",
    "chars": 1526,
    "preview": "// waysct is a set color temp implementation for Wayland.\n// Many of these files are taken from\n// https://github.com/mi"
  }
]

About this extraction

This page contains the full source code of the d4l3k/go-sct GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 26 files (72.2 KB), approximately 23.0k tokens, and a symbol index with 107 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!