Skip to content

Releases: salahu01/livewall-app

LiveWall for Windows 1.0.4

Pre-release

Choose a tag to compare

@salahu01 salahu01 released this 11 Aug 09:13
176b324

Windows-only release. The macOS, Linux and Android ports stay at 1.0.2 — nothing in this release touches them.

An import could fail after every frame had already been encoded

MF_MPEG4SINK_MOOV_BEFORE_MDAT asks the MP4 sink to put the moov atom ahead of the media data, so reopening the file does not read to the end first. On a wallpaper that is reopened every time the desktop becomes visible, that is the difference between an instant resume and a full-file read.

It is a request, not a guarantee. On some machines the rewrite the sink performs during Finalize() fails with E_ACCESSDENIED even though every WriteSample succeeded — so the import reported failure at the very end of a complete encode. The writer and the pump are now one retryable attempt: if the failure lands at Finalize(), the whole encode is retried once with the flag off, trading the fast-resume optimisation for a file that imports at all.

Video now plays on GPUs whose decoder textures cannot be bound directly

Seen on Intel UHD 630: the driver allocates the decoder's own texture array without D3D11_BIND_SHADER_RESOURCE, so CreateShaderResourceView fails with E_INVALIDARG on it no matter what the reader asks for at open time — and the wallpaper stayed blank. Each decoded slice is now copied on the same GPU into a plain texture the app owns and binds itself. The texture is kept across frames and only recreated when the frame size or format changes.

Notes

  • Unsigned. Windows SmartScreen will warn on first run.
  • Built by AppVeyor from 176b324. sha256 of LiveWall.exe:
    e966e52369fdefc228aedfcb6f65f5567d254a404242d3b6ca2030e66f82339e

LiveWall for Windows 1.0.3

Pre-release

Choose a tag to compare

@salahu01 salahu01 released this 10 Aug 13:06
7c6a19e

Windows-only release. The macOS, Linux and Android ports stay at 1.0.2 — nothing in this release touches them.

The executable now has an icon

LiveWall.exe has never shipped with an icon. tools/make-icon.ps1, which draws the .ico files at configure time, had never once run to completion:

  • The four PowerShell scripts had no byte-order mark. Windows PowerShell 5.1 reads a BOM-less .ps1 as the machine's ANSI codepage, not as UTF-8, so the em dashes inside string literals decoded under CP1252 to — — and that trailing U+201D closed the string early. A parse error, so nothing in the file ran. All four scripts now carry a UTF-8 BOM, and the dashes inside literals are plain hyphens. install.ps1 had the same defect, which means the documented install path has been broken under powershell.exe for as long as those lines existed.
  • Past that, both drawing functions addressed a namespace as a type: [System.Drawing.Drawing2D]::SmoothingMode::AntiAlias. The enum is System.Drawing.Drawing2D.SmoothingMode, so the whole dotted name belongs inside the brackets with a single ::.
  • Icons are now drawn at configure time rather than build time, so the .rc finds them when it is compiled.

The attached binary carries 11 RT_ICON images (7 app sizes, 4 tray sizes) and two RT_GROUP_ICON entries: 101 for the app icon and 102 for the tray. Explorer, the taskbar and Start resolve to the lowest group id, so they pick up the app icon, and the tray's LoadImageW(IDI_TRAYICON) now finds 102 instead of falling back to IDI_APPLICATION.

Import errors say which file was denied

An import that failed on a permissions error reported only that it failed. It now names the file it could not read.

Notes

  • Unsigned. Windows SmartScreen will warn on first run.
  • Built by AppVeyor from 7c6a19e. sha256 of LiveWall.exe:
    6174d515ca85e4db99df4d1780dec2e96124877fb9d18c19548c87f112cbf2ec

LiveWall 1.0.2 — Intel Macs and older Linux distros

Choose a tag to compare

@salahu01 salahu01 released this 07 Aug 15:45

A compatibility release. No new features — it fixes two ways 1.0.1 refused to
run on machines it claimed to support.

Both defects had the same shape: the build worked on the machine that produced
it, was unrunnable elsewhere, and nothing in the pipeline could tell.

macOS is now universal

1.0.1 shipped arm64 only. macOS 14 is the deployment target and Sonoma still
runs on the 2018-2020 Intel Macs, so every one of those was excluded by
architecture alone while meeting the stated requirement — and the bundle
assembled, signed and verified anyway.

LiveWall-macos.zip now carries both slices, each at minos 14.0. The x86_64
half was checked under Rosetta. bundle.sh builds both by default and prints
what it produced; LIVEWALL_ARCHS=arm64 restores the fast path for
development.

The macOS floor stays at 14.0. Lowering it needs an API audit and is not part
of this release.

The Linux binary now starts on old distros

1.0.1 would not run on the distro it was built on. AppVeyor's Ubuntu 20.04
image carries GCC 11.4, so the binary referenced GLIBCXX_3.4.29 while stock
focal provides GCC 10's runtime:

./livewall: /usr/lib/x86_64-linux-gnu/libstdc++.so.6:
  version `GLIBCXX_3.4.29' not found

The floor was being set by the compiler, not the distro, so building on an old
release bought nothing. libstdc++ and libgcc are now linked statically. glibc
stays dynamic — a static one breaks dlopen and NSS, which this app needs.

The binary went from 411 KB to 529 KB, and its only remaining floor is
glibc 2.25 (2017): Ubuntu 18.04, Debian 10, RHEL 8 and anything newer.

CI now fails if libstdc++ becomes dynamic again or any GLIBCXX_ reference
reappears, and prints the remaining glibc floor on every build. That check is
the actual deliverable — neither defect was visible from the build machine.

Still x86-64 only

Windows and Linux ship for x86-64 alone. Windows on ARM runs the x64 build
under emulation, which works but costs CPU continuously — the one thing this
app is built to avoid. Native ARM64 for both is a known gap, not an oversight.

Unchanged from 1.0.1

Everything else, including what is not verified: no CI runner has a GPU or a
desktop session, so on Windows the WorkerW parenting, Direct3D 11 and Media
Foundation decode paths have still never executed. The Linux Xvfb smoke test
remains the only runtime evidence in this project, and it runs without a render
node, so VA-API is untested.

Android is signed with the same key as 1.0.0 and 1.0.1 and installs over both.

Checksums (SHA-256)

60723aa234878a47d502654f2ad4efd3496fbdd57b74c19eab3c5cef1810e12e  LiveWall-macos.zip
cd742a10dc1bf78ea754f702a68406b025367bc0e1917e2cd44b4a9f88378a8a  LiveWall.exe
0627ec8860574811da2e323e9915e8049bdda6f05ea3fac0f317d83e0a705f9b  livewall
0c6c202e647f1a1c02c1d0140908a42517d75b34bc5a694639056077a4a05718  LiveWall-android.apk

LiveWall 1.0.1 — all four platforms

Choose a tag to compare

@salahu01 salahu01 released this 07 Aug 15:24

The first release carrying a build for every platform.

Platform Asset Built by
macOS 14+ (Apple silicon) LiveWall-macos.zip this machine
Windows 10+ (x64) LiveWall.exe AppVeyor, MSVC 19.44 + SDK 10.0.26100
Linux (x86-64) livewall AppVeyor, Ubuntu 20.04
Android 10+ LiveWall-android.apk this machine, signed

GitHub Actions built none of it — the account is billing-locked and every job
is refused before it starts. Windows and Linux come from AppVeyor, which this
release adds a Linux job to; macOS and Android are built locally because
AppVeyor's newest macOS image is 10.15 Catalina and the Android signing key
lives on one machine.

Fixes

The Linux port had never been compiled by anything either. Its first build
found two portability bugs, both from Ubuntu 20.04 being older than the
ubuntu-latest the Actions workflow assumed:

  • WaylandBackend.cpp installed a six-member wl_output_listener. name and
    description arrived with wl_output v4 in libwayland 1.20; 20.04 has 1.18,
    where that is a hard error. Both are now compiled only when the header
    declares them, and nothing is lost — they were already no-ops.
  • av_find_best_stream takes const AVCodec** from FFmpeg 5.0 and AVCodec**
    before it. The type is now deduced from the declaration actually in scope, so
    it is right on both without testing a version macro.

Also in this release, from the Windows port's first build:

  • Three missing SDK headers (shellapi.h for ShellExecuteW and
    CommandLineToArgvW, icodecapi.h for ICodecAPI).
  • A frame-pacing test that asserted the wrong rule.

Verified

  • macOS — builds, 31 tests pass, bundle signs and verifies.
  • Windows — builds, full unit suite passes.
  • Linux — builds, 10/10 ctest suites pass, and it is the one platform CI
    can actually run: under Xvfb it brought up an EGL 1.5 / GLES 3 context on
    X11, opened its control socket, detected the screen, reported
    state Rendering at 43.0 MB and exited cleanly. It also proves the
    dependency argument — libavcodec, libva, libdbus and libXss are all
    absent from the link line and opened with dlopen.
  • Android — builds, unit tests pass, signed with the same key as 1.0.0, so
    it installs over it.

Not verified

No GPU and no desktop session exists on any runner, so on Windows the
WorkerW parenting, Direct3D 11 rendering and Media Foundation decode paths
have still never executed, and on macOS and Android the decode paths
are exercised only by hand. The Linux smoke test is the sole runtime evidence
in this release, and it ran without a render node, so its VA-API path is
untested too.

Checksums (SHA-256)

b238a201a28418ee03aa507f05636a72abf1ab9d380527166650b23483d80fbc  LiveWall-macos.zip
7b677e776f7283e6f08dfdf3002fa5a1694ce599de531c02c9f182e3e7d04a75  LiveWall.exe
be35477939c9da80bcb688f4ed276a2054a3f6eb5c128f9fb6397fbcc60a571f  livewall
222a611d09a36956e5202b7730ca755cf3dafefe76c93948ab5dc963c0f15b0e  LiveWall-android.apk

LiveWall for Android 1.0.0

Choose a tag to compare

@salahu01 salahu01 released this 07 Aug 07:37

The first release of the Android port. A live wallpaper built around one
constraint: it should cost almost nothing when you aren't looking at it.

When the wallpaper stops being visible — any app in front, screen off, device
locked — the MediaCodec and its buffer pool are destroyed, not paused. The
last frame stays on screen composited by SurfaceFlinger at no cost, and playback
resumes from the saved timestamp.

State Memory (PSS) CPU
Video, 1920×1080 24 fps, wallpaper visible 44 MB 12.3%
Video, wallpaper hidden 32 MB 0.00%

⚠️ These are emulator numbers and the CPU figure is not representative. They
come from an API 35 arm64 emulator with hw.gpu.enabled=no — software AVC decode
and a SwiftShader GL stack, i.e. every fixed-function block this design depends
on replaced by the CPU. No hardware-device measurements have been taken. The
teardown result on the second row is codec-independent and stands; the
visible-state CPU figure is not a phone number and is not quoted as one.

111 KB. No AndroidX, no Compose, no Material, no media3, no bundled ffmpeg
— the shipped runtime classpath is the Kotlin standard library and nothing else.

Install

Requires Android 10 (API 29) or newer.

adb install LiveWall-android-1.0.0.apk

Then open LiveWall, add a video, and set it as your wallpaper. Videos are
converted on import and only the converted file is played; your original is never
copied or modified.

The APK is signed with a self-signed key, not distributed through Play, so your
device will ask you to allow installation from this source. Signing certificate:

CN=LiveWall, O=Fegno Technologies, C=IN
SHA-256  f5:6b:aa:64:f4:4c:ad:a6:e9:65:b4:33:cc:f4:3a:33:8b:5f:81:92:e3:d5:d2:4b:6a:9e:14:75:73:29:43:28

Or build it yourself — see platforms/android/README.md:

cd platforms/android && ./tools/build.sh install

Known limits

  • No hardware-device measurements, as above.
  • OEM skins are untested. Some launchers keep the wallpaper permanently
    hidden behind a blur layer, some never report visibility correctly, and some
    aggressively kill wallpaper services. Nothing here has been exercised beyond
    stock Android.
  • The gradient mode is not free, unlike its macOS counterpart —
    SurfaceFlinger will not animate a buffer for you, so the drift is redrawn from
    the app process at 10 fps.
  • No parallax on launcher scroll, deliberately: it would mean redrawing at
    the panel's refresh rate rather than the wallpaper's.
  • One wallpaper. No playlist, no separate lock-screen wallpaper.
  • The thermal and low-battery gates are coded but not observed firing — the
    conditions are awkward to stage deliberately.
  • 10-bit is best-effort. It needs both an encoder advertising HEVC Main10 and
    an EGL config with 10 bits per channel; where either is missing the import
    quietly produces 8-bit and records that.

Verified for this build

55 unit tests — frame pacing, output sizing, fit geometry, index decoding — pass
against the tagged tree. The decode and transcode paths need a real codec and
live in androidTest, which needs a device; they were not run for this release.


The macOS port is
where this design was worked out and measured. The Windows and Linux ports are in
the tree but are not released.

LiveWall for Windows 1.0.0

Pre-release

Choose a tag to compare

@salahu01 salahu01 released this 07 Aug 14:36

The first compiled build of the Windows port.

LiveWall.exe — 386 KB, PE32+ GUI x86-64, no installer and no runtime
dependencies beyond the Windows SDK libraries that ship with the OS.

Built by AppVeyor from b42f894 with MSVC 19.44 and Windows SDK 10.0.26100.
GitHub Actions could not run: the account is billing-locked and every job is
refused before it starts.

What this build fixed

The port had been published but never compiled by anything. Its first contact
with a compiler surfaced four defects, all fixed here:

  • Paths.cpp used ShellExecuteW without including shellapi.h.
  • Transcoder.cpp used ICodecAPI with only codecapi.h included, which
    carries the CODECAPI_* GUIDs but not the interface they are passed to.
  • main.cpp used CommandLineToArgvW, also from shellapi.h.
  • The frame-pacing suite asserted pacedFPS(24, 13) == 24. The code was right
    and the test was wrong — a 13 Hz panel cannot present 24 fps, and the
    below-12 floor the case meant to exercise is only reachable when the refresh
    exceeds the requested rate.

Verified

  • Compiles and links clean under MSVC.
  • The full unit suite passes: coverage geometry, frame pacing, output sizing,
    index decoding.

Not verified — why this is a pre-release

Nothing in this build has run on a real desktop. The suite is pure logic
because a CI worker has no display session and no GPU, so the three things
that make this a wallpaper rather than a library are entirely unexercised:

  • WorkerW parenting — attaching the render surface behind the desktop icons.
  • Direct3D 11 rendering — device creation, the swap chain, the shaders.
  • Media Foundation decode — the import pipeline and playback.

Treat this as "it builds and its arithmetic is correct", not "it works".
If it runs on your machine, please say so on the issue tracker.

Try it

LiveWall.exe --probe            what this machine can encode and decode
LiveWall.exe                    the tray app

--probe is the safest first command: it reports codec support and exits
without touching the desktop.

LiveWall 1.0.0

Choose a tag to compare

@salahu01 salahu01 released this 06 Aug 17:04

A status-bar live wallpaper for macOS, built so it costs almost nothing when you aren't looking at it.

Measured on an M3 Pro with a 3024×1964 panel:

State Memory CPU
Video, 3492×1964 10-bit 24 fps HEVC, desktop visible 19 MB 2.9%
Desktop covered 12 MB 0.0%
Procedural gradient mode 12 MB 0.0%

CPU is a percentage of one core.

Install

⚠️ This build is ad-hoc signed, not notarized. Gatekeeper will refuse it on first open. Either build from source (recommended), or right-click the app → Open → Open.

Build from source:

git clone https://github.com/salahu01/LiveWall.git
cd LiveWall
./tools/install.sh

Install before enabling Open at Login — SMAppService reports notFound for an app run out of a build directory, so the toggle silently does nothing.

What's in it

  • Occlusion tears the decoder down rather than pausing it, and partial coverage counts: the uncovered desktop fraction comes from the window list, because NSWindow.occlusionState still says "visible" when a window covers all but a corner.
  • Rendering also stops on screen lock, display sleep, screensaver, thermal pressure, Low Power Mode, battery under 20%, and 15 minutes without input.
  • Import is mandatory — everything is transcoded to HEVC, sized to cover your display without upscaling, and paced to a divisor of its refresh rate.
  • Fill / Fit / Stretch scaling, switchable live with no re-encode.
  • 31 tests over the logic that can fail quietly.

Requires macOS 14 or later.