Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[Unit]
Description=Bluefin Dynamic Wallpaper
After=graphical-session.target

[Service]
Type=oneshot
ExecStart=/usr/libexec/bluefin-dynamic-wallpaper
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[Unit]
Description=Run Bluefin Dynamic Wallpaper daily

[Timer]
OnBootSec=1min
OnUnitActiveSec=24h
Persistent=true

[Install]
WantedBy=graphical-session.target
58 changes: 58 additions & 0 deletions system_files/bluefin/usr/libexec/bluefin-dynamic-wallpaper
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#!/usr/bin/env bash
set -euo pipefail

readonly WALLPAPER_BASE_PATH="/usr/share/backgrounds/bluefin"

CURRENT_WALLPAPER="$(gsettings get org.gnome.desktop.background picture-uri)"
CURRENT_WALLPAPER="${CURRENT_WALLPAPER#\'file://}"
CURRENT_WALLPAPER="${CURRENT_WALLPAPER%\'}"

CURRENT_WALLPAPER_DARK="$(gsettings get org.gnome.desktop.background picture-uri-dark)"
CURRENT_WALLPAPER_DARK="${CURRENT_WALLPAPER_DARK#\'file://}"
CURRENT_WALLPAPER_DARK="${CURRENT_WALLPAPER_DARK%\'}"

if [[ "$CURRENT_WALLPAPER" != "${WALLPAPER_BASE_PATH}"/*-bluefin.xml ]] ||
[[ "$CURRENT_WALLPAPER_DARK" != "${WALLPAPER_BASE_PATH}"/*-bluefin.xml ]]; then
echo "User has a personal wallpaper set. Not changing it."
exit 0
fi

MONTH="$(date +%m)"
MONTH_NUM="${MONTH#0}"

LATITUDE="$(/usr/libexec/get-geoclue-latitude)" && LOCATION_EXIT=0 || LOCATION_EXIT=$?

HEMISPHERE="north"

if [[ $LOCATION_EXIT -eq 2 ]]; then
echo "Location services disabled or denied, defaulting to northern hemisphere"
elif [[ $LOCATION_EXIT -ne 0 ]]; then
echo "Error getting location, defaulting to northern hemisphere"
elif ! [[ "$LATITUDE" =~ ^-?[0-9]+\.?[0-9]*$ ]]; then
echo "Invalid latitude format: $LATITUDE, defaulting to northern hemisphere"
elif [[ "${LATITUDE:0:1}" == "-" ]]; then
HEMISPHERE="south"
# Add 6 months for southern hemisphere seasons; months are 1-12 so adjust before modulo.
MONTH_NUM=$(( (MONTH_NUM + 5) % 12 + 1 ))
fi

if [[ $MONTH_NUM -lt 10 ]]; then
MONTH_PADDED="0$MONTH_NUM"
else
MONTH_PADDED="$MONTH_NUM"
fi

WALLPAPER_PATH="${WALLPAPER_BASE_PATH}/${MONTH_PADDED}-bluefin.xml"

if [[ ! -f "$WALLPAPER_PATH" ]]; then
echo "Wallpaper file not found: $WALLPAPER_PATH" >&2
exit 1
fi

if gsettings set org.gnome.desktop.background picture-uri "file://$WALLPAPER_PATH" &&
gsettings set org.gnome.desktop.background picture-uri-dark "file://$WALLPAPER_PATH"; then
echo "Successfully set wallpaper to $WALLPAPER_PATH (adjusted month: $MONTH_NUM, hemisphere: $HEMISPHERE)"
else
echo "Failed to set wallpaper" >&2
exit 1
fi
131 changes: 131 additions & 0 deletions system_files/bluefin/usr/libexec/get-geoclue-latitude
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
#!/usr/bin/env bash
set -euo pipefail

readonly LOCATION_TIMEOUT_SECONDS=30
readonly POLL_INTERVAL=0.5
readonly MAX_ATTEMPTS=$(( LOCATION_TIMEOUT_SECONDS * 2 ))

CLIENT_PATH=""

cleanup() {
if [[ -n "$CLIENT_PATH" ]]; then
gdbus call --system \
--dest org.freedesktop.GeoClue2 \
--object-path "$CLIENT_PATH" \
--method org.freedesktop.GeoClue2.Client.Stop &>/dev/null || true
fi
}
trap cleanup EXIT

if ! command -v gdbus &>/dev/null; then
echo "error: gdbus not found" >&2
exit 1
fi

CREATE_OUTPUT="$(gdbus call --system \
--dest org.freedesktop.GeoClue2 \
--object-path /org/freedesktop/GeoClue2/Manager \
--method org.freedesktop.GeoClue2.Manager.CreateClient 2>&1)" || {
if [[ "$CREATE_OUTPUT" == *"org.freedesktop.DBus.Error.AccessDenied"* ]]; then
echo "error: location services disabled or denied" >&2
exit 2
fi
echo "error: failed to create GeoClue2 client: $CREATE_OUTPUT" >&2
exit 1
}

CLIENT_PATH="$(sed -n "s|.*'\(/org/freedesktop/GeoClue2/Client/[0-9]*\)'.*|\1|p" <<< "$CREATE_OUTPUT")"
if [[ -z "$CLIENT_PATH" ]]; then
echo "error: failed to parse client path from: $CREATE_OUTPUT" >&2
exit 1
fi

run_gdbus() {
local description="$1"
shift
local output

output="$(gdbus call --system "$@" 2>&1)" || {
if [[ "$output" == *"org.freedesktop.DBus.Error.AccessDenied"* ]]; then
echo "error: location services disabled or denied" >&2
exit 2
fi
echo "error: failed to $description: $output" >&2
exit 1
}

printf '%s\n' "$output"
}

run_gdbus "set GeoClue2 DesktopId" \
--dest org.freedesktop.GeoClue2 \
--object-path "$CLIENT_PATH" \
--method org.freedesktop.DBus.Properties.Set \
org.freedesktop.GeoClue2.Client DesktopId \
"<'bluefin-dynamic-wallpaper'>" >/dev/null

run_gdbus "set GeoClue2 RequestedAccuracyLevel" \
--dest org.freedesktop.GeoClue2 \
--object-path "$CLIENT_PATH" \
--method org.freedesktop.DBus.Properties.Set \
org.freedesktop.GeoClue2.Client RequestedAccuracyLevel \
"<uint32 4>" >/dev/null

run_gdbus "start GeoClue2 client" \
--dest org.freedesktop.GeoClue2 \
--object-path "$CLIENT_PATH" \
--method org.freedesktop.GeoClue2.Client.Start >/dev/null

ATTEMPT=0
LOCATION_PATH=""
while (( ATTEMPT < MAX_ATTEMPTS )); do
LOC_OUTPUT="$(gdbus call --system \
--dest org.freedesktop.GeoClue2 \
--object-path "$CLIENT_PATH" \
--method org.freedesktop.DBus.Properties.Get \
org.freedesktop.GeoClue2.Client Location 2>/dev/null)" || true

LOCATION_PATH="$(sed -n "s|.*'\(/org/freedesktop/GeoClue2/Location/[0-9]*\)'.*|\1|p" <<< "$LOC_OUTPUT")"
if [[ -n "$LOCATION_PATH" ]]; then
break
fi

sleep "$POLL_INTERVAL"
(( ATTEMPT += 1 ))
done

if [[ -z "$LOCATION_PATH" ]]; then
echo "error: location unavailable after ${LOCATION_TIMEOUT_SECONDS}s timeout" >&2
exit 1
fi

LAT_OUTPUT="$(run_gdbus "read latitude" \
--dest org.freedesktop.GeoClue2 \
--object-path "$LOCATION_PATH" \
--method org.freedesktop.DBus.Properties.Get \
org.freedesktop.GeoClue2.Location Latitude)"

LATITUDE="$(sed -n 's|.*<\(double \)\?\(-\?[0-9][0-9]*\.\?[0-9]*\)>.*|\2|p' <<< "$LAT_OUTPUT")"
if [[ -z "$LATITUDE" ]]; then
echo "error: failed to parse latitude from: $LAT_OUTPUT" >&2
exit 1
fi

LON_OUTPUT="$(run_gdbus "read longitude" \
--dest org.freedesktop.GeoClue2 \
--object-path "$LOCATION_PATH" \
--method org.freedesktop.DBus.Properties.Get \
org.freedesktop.GeoClue2.Location Longitude)"

LONGITUDE="$(sed -n 's|.*<\(double \)\?\(-\?[0-9][0-9]*\.\?[0-9]*\)>.*|\2|p' <<< "$LON_OUTPUT")"
if [[ -z "$LONGITUDE" ]]; then
echo "error: failed to parse longitude from: $LON_OUTPUT" >&2
exit 1
fi

if [[ "$LATITUDE" =~ ^-?0+(\.0+)?$ ]] && [[ "$LONGITUDE" =~ ^-?0+(\.0+)?$ ]]; then
echo "error: coordinates are (0.0, 0.0), likely uninitialized" >&2
exit 1
fi

echo "$LATITUDE"
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail

# shellcheck disable=SC1091
source /usr/lib/ublue/setup-services/libsetup.sh

version-script dynamic-wallpaper user 1 || exit 0

echo "Enabling dynamic wallpaper timer"
systemctl --user enable --now bluefin-dynamic-wallpaper.timer
Loading