Compare commits

10 Commits

10 changed files with 234 additions and 6660 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
profiles/
*.json

29
all_attributes.md Normal file
View File

@@ -0,0 +1,29 @@
# All Kscreen Doctor attributes
- [x] primary
- [x] priority
- [x] enable
- [x] disable
- [x] mode
- [x] position
- [x] scale
- [x] orientation / rotation
- [x] overscan (0-100)
- [x] vrrpolicy (never / always / automatic)
- [x] rgbrange (automatic / full / limited)
- [x] hdr (enable / disable / toggle)
- [x] sdr-brightness (50-10000)
- [x] wcg (enable / disable / toggle)
- [x] iccprofile (path)
- [ ] sdrGamut (0-100)
- [ ] maxBrightnessOverride (disable / int)
- [ ] maxAverageBrightnessOverride (disable / int)
- [ ] minBrightnessOverride (disable / int)
- [ ] colorProfileSource (sRBG / ICC / EDID)
- [x] brightness (0-100)
- [ ] colorPowerTradeoff (preferEfficiency / preferAccuracy)
- [ ] dimming (0-100)
- [x] mirror ( none / output )
- [x] ddcCi (allow / disallow)
- [x] maxbpc (automatic / 6-16)
- [ ] edrPolicy (never / always)
- [ ] sharpness (0 - 100)

View File

@@ -1,15 +0,0 @@
#!/bin/bash
# Make sure a config file was provided
if [ $# -lt 1 ]; then
echo "Usage: $0 <config file>"
exit
fi
# Attempt to parse the config file
INPUT_FILE=$1
echo "Parsing config info from $INPUT_FILE..."
TEST=$(jq '.outputs[]' $INPUT_FILE)
echo $TEST[0]

View File

@@ -1,5 +1,12 @@
#!/usr/bin/env bash #!/usr/bin/env bash
VERBOSE=1
function log {
if [ $VERBOSE -eq 1 ]; then
echo "$@"
fi
}
set -e set -e
# Make sure a config file was provided # Make sure a config file was provided
@@ -25,73 +32,217 @@ if ! command -v kscreen-doctor &>/dev/null; then
exit 1 exit 1
fi fi
#######################
# Parse JSON + restore
#######################
# Extract outputs list # Extract outputs list
enabled_outputs=$(jq -c '.outputs[] | select(.enabled == true)' "$PROFILE")
disabled_outputs=$(jq -c '.outputs[] | select(.enabled == false)' "$PROFILE")
outputs=$(jq -c '.outputs[]' "$PROFILE") outputs=$(jq -c '.outputs[]' "$PROFILE")
# 1. Restore enabled/disabled + basic properties # Restore enabled/disabled starting with the enabled monitors
while IFS= read -r out; do # Starting with a disabled monitor might not work if it was
id=$(echo "$out" | jq -r '.id') # previously the only enabled monitor
enabled=$(echo "$out" | jq -r '.enabled')
posx=$(echo "$out" | jq -r '.pos.x')
posy=$(echo "$out" | jq -r '.pos.y')
rotation=$(echo "$out" | jq -r '.rotation')
scale=$(echo "$out" | jq -r '.scale')
mode=$(echo "$out" | jq -r '.currentModeId')
priority=$(echo "$out" | jq -r '.priority')
# Enable/disable function enable_outputs {
if [[ "$enabled" == "true" ]]; then local outputs=$1
kscreen-doctor "output.$id.enable"
# If empty or only whitespace, return early
[[ -z "$outputs" ]] && return
while IFS= read -r out; do
id=$(echo "$out" | jq -r '.id')
log "[VAR] id:" $id
name=$(echo "$out" | jq -r '.name')
log "[VAR] name:" $name
enabled=$(echo "$out" | jq -r '.enabled')
log "[VAR] enabled:" $enabled
# Enable/disable
if [[ "$enabled" == "true" ]]; then
CMD="kscreen-doctor output.$name.enable"
log "[CMD]" $CMD
$CMD
else
CMD="kscreen-doctor output.$name.disable"
log "[CMD]" $CMD
$CMD
fi
done <<< "$outputs"
}
log "Enabling enabled outputs..."
enable_outputs "$enabled_outputs"
log "Disabling disabled outputs..."
enable_outputs "$disabled_outputs"
function apply_attribute {
output_id=$1
attribute=$2
value=$3
value_map=$4
if [ $value != "null" ]; then
if [[ -n "$value_map" ]]; then
log "[PREVALUE] Value supplied for $output_id $attribute: $value"
value=${value_map["$value"]}
log "[POSTVALUE] Value output for $output_id $attribute: $value"
fi
CMD="kscreen-doctor output.$output_id.$attribute.$value"
log "[CMD]" $CMD
$CMD
else else
kscreen-doctor "output.$id.disable" log "Output $output_id has not attribute $attribute, skipping..."
continue
fi fi
}
# Mode (Resolution + refresh) function load_profile_to_outputs {
kscreen-doctor "output.$id.mode.$mode" local outputs=$1
# Position # If empty or only whitespace, return early
kscreen-doctor "output.$id.position.$posx,$posy" [[ -z "$outputs" ]] && return
# Scale while IFS= read -r out; do
kscreen-doctor "output.$id.scale.$scale" id=$(echo "$out" | jq -r '.id')
name=$(echo "$out" | jq -r '.name')
# Rotation (map from JSON names to kscreen-doctor options) posx=$(echo "$out" | jq -r '.pos.x')
case "$rotation" in posy=$(echo "$out" | jq -r '.pos.y')
"1") kscreen-doctor "output.$id.rotation.normal" ;; rotation=$(echo "$out" | jq -r '.rotation')
"2") kscreen-doctor "output.$id.rotation.left" ;; scale=$(echo "$out" | jq -r '.scale')
"4") kscreen-doctor "output.$id.rotation.inverted" ;; mode_id=$(echo "$out" | jq -r '.currentModeId')
"8") kscreen-doctor "output.$id.rotation.right" ;; brightness=$(echo "$out" | jq -r '.brightness')
esac brightness=$(awk "BEGIN {printf \"%d\", $brightness * 100}")
ddcCi=$(echo "$out" | jq -r '.ddcCi')
# Primary / Not Primary iccProfilePath=$(echo "$out" | jq -r '.iccProfilePath')
echo $priority # mode_name=$(echo "$out" | jq -r ".modes[] | select(.id == \"$mode_id\") | .name")
if [ $priority -eq 1 ]; then # log "[VAR] mode_name:" $mode_name
kscreen-doctor "output.$id.primary" refresh_rate=$(echo "$out" | jq -r ".modes[] | select(.id == \"$mode_id\") | .refreshRate")
fi refresh_rate=$(printf "%.0f" "$refresh_rate")
height=$(echo "$out" | jq -r ".modes[] | select(.id == \"$mode_id\") | .size.height")
width=$(echo "$out" | jq -r ".modes[] | select(.id == \"$mode_id\") | .size.width")
mode="${width}x${height}@${refresh_rate}"
replication_source_id=$(echo "$out" | jq -r ".replicationSource")
hdr=$(echo "$out" | jq -r ".hdr")
maxBpc=$(echo "$out" | jq -r ".maxBpc")
overscan=$(echo "$out" | jq -r ".overscan")
rgbRange=$(echo "$out" | jq -r ".rgbRange")
sdrbrightness=$(echo "$out" | jq -r '."sdr-brightness"')
vrrPolicy=$(echo "$out" | jq -r ".vrrPolicy")
wcg=$(echo "$out" | jq -r ".wcg")
done <<< "$outputs" declare -A bool_enable_map
bool_enable_map["true"]="enable"
bool_enable_map["false"]="disable"
declare -A rgb_range_map
rgb_range_map["0"]="automatic"
rgb_range_map["full"]="full"
rgb_range_map["limited"]="limited"
######################### apply_attribute $name "wcg" $wcg $bool_enable_map
# 2. Restore clone groups
#########################
clone_groups=$(jq -c '.clones[]?' "$PROFILE") apply_attribute $name "sdr-brightness" $sdrbrightness
while IFS= read -r clone; do apply_attribute $name "vrrpolicy" $vrrPolicy
primary=$(echo "$clone" | jq -r '.[0]')
others=$(echo "$clone" | jq -r '.[]' | tail -n +2)
for o in $others; do apply_attribute $name "rgbrange" $rgbRange $rgb_range_map
kscreen-doctor "output.$o.clone.$primary"
done CMD="kscreen-doctor output.$name.overscan.$overscan"
done <<< "$clone_groups" log "[CMD]" $CMD
$CMD
if [ "$maxBpc" == 0 ]; then
CMD="kscreen-doctor output.$name.maxbpc.automatic"
else
CMD="kscreen-doctor output.$name.maxbpc.$maxBpc"
fi
log "[CMD]" $CMD
$CMD
if [ "$hdr" == true ]; then
CMD="kscreen-doctor output.$name.hdr.enable"
else
CMD="kscreen-doctor output.$name.hdr.disable"
fi
log "[CMD]" $CMD
$CMD
log "[VAR] replication_source_id: $replication_source_id"
if [ $replication_source_id != 0 ]; then
replication_source_name=$(echo "$outputs.[] | select(.id == \"$replication_source_id\" | .name)" )
log "[VAR] replication_source_name: $replication_source_name"
CMD="kscreen-doctor output.$name.mirror.$replication_source_name"
log "[CMD]" $CMD
$CMD
else
CMD="kscreen-doctor output.$name.mirror.none"
log "[CMD]" $CMD
$CMD
fi
log "[VAR] mode: $mode"
priority=$(echo "$out" | jq -r '.priority')
if [ $ddcCi == true ]; then
CMD="kscreen-doctor output.$name.ddcCi.allow"
else
CMD="kscreen-doctor output.$name.ddcCi.disallow"
fi
log "[CMD]" $CMD
$CMD
if [ "$iccProfilePath" != "" ]; then
CMD="kscreen-doctor output.$name.iccProfilePath.$iccProfilePath"
log "[CMD]" $CMD
$CMD
fi
CMD="kscreen-doctor output.$name.brightness.$brightness"
log "[CMD]" $CMD
$CMD
#
# Mode (Resolution + refresh)
# CMD="kscreen-doctor output.$name.mode.$mode"
CMD="kscreen-doctor output.$name.mode.$mode"
log "[CMD]" $CMD
$CMD
# Position
CMD="kscreen-doctor output.$name.position.$posx,$posy"
log "[CMD]" $CMD
$CMD
# Scale
CMD="kscreen-doctor output.$name.scale.$scale"
log "[CMD]" $CMD
$CMD
# Rotation (map from JSON names to kscreen-doctor options)
CMD=""
case "$rotation" in
"1") CMD="kscreen-doctor output.$name.rotation.normal" ;;
"2") CMD="kscreen-doctor output.$name.rotation.left" ;;
"4") CMD="kscreen-doctor output.$name.rotation.inverted" ;;
"8") CMD="kscreen-doctor output.$name.rotation.right" ;;
esac
log "[CMD]" $CMD
$CMD
# Primary / Not Primary
if [ $priority -eq 1 ]; then
CMD="kscreen-doctor output.$name.primary"
log "[CMD]" $CMD
$CMD
fi
CMD="kscreen-doctor output.$name.priority.$priority"
log "[CMD]" $CMD
$CMD
done <<< "$outputs"
}
load_profile_to_outputs "$outputs"
echo "Display configuration restored." echo "Display configuration restored."

View File

@@ -1,108 +0,0 @@
#!/usr/bin/env bash
set -e
# Make sure a config file was provided
if [ $# -lt 1 ]; then
echo "Usage: $0 <config file>"
exit
fi
PROFILE=$1
if [[ ! -f "$PROFILE" ]]; then
echo "Profile file not found: $PROFILE" >&2
exit 1
fi
if ! command -v jq &>/dev/null; then
echo "jq not installed!" >&2
exit 1
fi
if ! command -v kscreen-doctor &>/dev/null; then
echo "kscreen-doctor not found!" >&2
exit 1
fi
#######################
# Parse JSON + ordering
#######################
# Extract output entries based on positions
origin_out=$(jq -c '.outputs[] | select(.pos.x == 0 and .pos.y == 0 and .enabled == true)' "$PROFILE")
non_origin_outs=$(jq -c '.outputs[] | select(.pos.x != 0 or .pos.y != 0 or .enable == false)' "$PROFILE")
#######################
# Function: Apply output
#######################
apply_output() {
local out="$1"
id=$(echo "$out" | jq -r '.id')
posx=$(echo "$out" | jq -r '.pos.x')
posy=$(echo "$out" | jq -r '.pos.y')
rotation=$(echo "$out" | jq -r '.rotation')
scale=$(echo "$out" | jq -r '.scale')
mode=$(echo "$out" | jq -r '.currentModeId')
priority=$(echo "$out" | jq -r '.priority')
enabled=$(echo "$out" | jq -r '.enabled')
# Enable/disable
if [[ "$enabled" == "true" ]]; then
kscreen-doctor "output.$id.enable"
else
kscreen-doctor "output.$id.disable"
return
fi
# Mode
kscreen-doctor "output.$id.mode.$mode"
# Position
kscreen-doctor "output.$id.position.$posx,$posy"
# Scale
kscreen-doctor "output.$id.scale.$scale"
# Rotation
case "$rotation" in
"1") kscreen-doctor "output.$id.rotation.normal" ;;
"2") kscreen-doctor "output.$id.rotation.left" ;;
"4") kscreen-doctor "output.$id.rotation.inverted" ;;
"8") kscreen-doctor "output.$id.rotation.right" ;;
esac
# Primary
if [ "$priority" -eq 1 ]; then
kscreen-doctor "output.$id.primary"
fi
}
if [[ -n "$origin_out" ]]; then
apply_output "$origin_out"
fi
while IFS= read -r out; do
apply_output "$out"
done <<< "$non_origin_outs"
#########################
# 3. Restore clone groups
#########################
clone_groups=$(jq -c '.clones[]?' "$PROFILE")
while IFS= read -r clone; do
primary=$(echo "$clone" | jq -r '.[0]')
others=$(echo "$clone" | jq -r '.[]' | tail -n +2)
for o in $others; do
kscreen-doctor "output.$o.clone.$primary"
done
done <<< "$clone_groups"
echo "Display configuration restored."

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff