revive Windows port#541
Merged
Merged
Conversation
Early update of MSVC project : - Using Visual Studio 2022 Community - Using Clang-cl (clang + MSVC runtime) - Fix some mac only stuff - OSD.hpp duplicated to client (will need to be fixed in Xcode)
Getting to DirectX
Notes : - Event handling seems to have changed a lot in new client, will probably need to be redone for windows - Update requires extra parameters now - Still some intrinsic thing going on
Boost library 1.83 from https://sourceforge.net/projects/boost/files/boost-binaries/1.83.0/ We need the msvc 14.3 (aka vc143) static variants in both mt-gd (releases) and mt-sgd (debug)
Fix virtual functions added for Metal in DX renderer
Add virtual functions exclusively used by DX renderer
Switch to msvc's _aligned_buffer to allocate buffers directly aligned to page sizes. Most of this code seems to have been here only to deal with the lack of valloc on windows, and can probably be simplified further.
Additional fixes to correctly free the aligned buffers on windows
Using boost::log to get rid of the custom posix only implementation
Crashes the msvc runtime
- Fix somehow expected decoder frames that aren't quite there yet for a few ms. Could be it's not an issue with videotoolbox hw acceleration on Mac but is an issue with the software path. FFmpeg decoding threads seems to work and decode thread now - Fix FFMPEG error that were disabled - Implement thread naming on windows - TODO : Find an equivalent for Mac's GCD dispatch_after / dispatch on main queue - Demote some repetitive useless logging from curl to trace level
Move content to ` C:\ProgramData\e-dream` by default (safe location on all modern windows systems).
New build target `DebugMD` should now be used to build and debug. Libpng does require MD (multi threaded DLL compilation), this will likely also fix socket.io which also seemed to require this.
Move to DX12 headers from github as Agility SDK requires dll building
Remove old DirectX renderer Fix various includes/imports, remove old SDK so that only DX12 remains and no conflict arises Start moving client_win32 to D3D12
WIP TextureFlat
Move stuff to DeviceResources + DirectXTK (both from Microsoft, they supposedly simplify D3D12 handling and handle HDR) Add texture loading (nearly done)
Anytime a GPU resource is needed, piggyback to DisplayOutputD3D12 that contains a unique_ptr to DirectX12 resources
Basic run loop with DX12 is now updating frames
Aligning on new changes on Mac
# Conflicts: # client_generic/Networking/EDreamClient.cpp
This was referenced Apr 15, 2026
Closed
Closed
Closed
scottdraves
added a commit
that referenced
this pull request
Apr 15, 2026
PR #541 accidentally re-added the removed lua distribution as lua5.1-old/ — ~200 files including IDE state and build artifacts. Nothing in the build references it. Also extend .gitignore to prevent .vs/, *.vsidx, *.tlog, *.obj, *.pdb, *.idb from slipping in again. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
scottdraves
added a commit
that referenced
this pull request
Apr 15, 2026
PR #541 accidentally re-added the removed lua distribution as lua5.1-old/ — ~200 files including IDE state and build artifacts. Nothing in the build references it. Also extend .gitignore to prevent .vs/, *.vsidx, *.tlog, *.obj, *.pdb, *.idb from slipping in again. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
scottdraves
added a commit
that referenced
this pull request
Apr 15, 2026
The 4.6 MB debug build of e-dreamd.exe leaked into RuntimeMSVC/ from PR #541. .gitignore already ignores client_generic/RuntimeMSVC/*.exe, but the file predated that rule. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
scottdraves
added a commit
that referenced
this pull request
Apr 17, 2026
Upgrades OpenSSL 1.0.2k (EOL 2019) to 3.6.1 via the existing vcpkg manifest, and removes the vendored Windows binary blobs for ffmpeg, boost, and curl that PR #541 introduced. Progress toward #549 — the socket.io-client-cpp lib dir (219 MB) is intentionally left for a follow-up once the WebSocket reconnect regression under vcpkg asio is root-caused. Cleaned electricsheep.vcxproj across all 8 configs: removed hardcoded absolute paths (C:\boost_1_*, C:\local\boost_1_85_0, C:\Users\Jack\... openssl build tree), vendored dep paths (..\ffmpeg\..., ..\openssl-1.0.2k, ..\curl\lib\...), CURL_STATICLIB define, and OpenSSL 1.0-era library names (libeay32, ssleay32). Vcpkg manifest integration auto-resolves include/lib paths via VCPKG_ROOT. Deleted (216 MB, 346 files): client_generic/ffmpeg/win32/ffmpeg-6.1.1-93/ 117 MB client_generic/openssl-1.0.2k/windows/ 62 MB client_generic/boost/win32/lib/ 23 MB client_generic/curl/lib/debug-ssl-zlib/ 14 MB Verified Release|x64 build (0 errors) and runtime: HTTPS auth, video playback, and WebSocket remote control all work against api-alpha with vcpkg's OpenSSL 3.6.1, libcurl, ffmpeg, and boost DLLs. Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
This was referenced Apr 17, 2026
scottdraves
added a commit
that referenced
this pull request
Apr 22, 2026
PR #541 bumped the vcpkg submodule past upstream commit b94ab47c99 ("[ffmpeg] Remove deprecated securetransport"), which silently dropped the implicit --enable-securetransport on macOS/iOS. The Apr 16 rebuild produced libavformat.a with no TLS backend (no ff_openssl, ff_securetransport, or ff_gnutls symbols), breaking the Player::PlayDreamNow uncached-streaming path with: FFmpeg warning: https or dtls protocol not found Failed to open URL https://... Enable the openssl feature for ffmpeg on !windows (Mac reads /etc/ssl/cert.pem, Linux reads the distro bundle; OpenSSL 3.6.1 is already linked for libcurl since 823d072). Leave Windows on the portfile's default --enable-schannel, which reads the Windows cert store natively; vcpkg's curl[ssl] port already defaults to sspi on Windows for the same reason. Also document the runtime log path (/Users/Shared/infinidream.ai/Logs/) in AGENTS.md. Related: #556 will eventually supersede this by removing ffmpeg's TLS dependency entirely (use libcurl for all network). Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
scottdraves
added a commit
that referenced
this pull request
Apr 22, 2026
PR #541 bumped the vcpkg submodule past upstream commit b94ab47c99 ("[ffmpeg] Remove deprecated securetransport"), which silently dropped the implicit --enable-securetransport on macOS/iOS. The Apr 16 rebuild produced libavformat.a with no TLS backend (no ff_openssl, ff_securetransport, or ff_gnutls symbols), breaking the Player::PlayDreamNow uncached-streaming path with: FFmpeg warning: https or dtls protocol not found Failed to open URL https://... Enable the openssl feature for ffmpeg on !windows (Mac reads /etc/ssl/cert.pem, Linux reads the distro bundle; OpenSSL 3.6.1 is already linked for libcurl since 823d072). Leave Windows on the portfile's default --enable-schannel, which reads the Windows cert store natively; vcpkg's curl[ssl] port already defaults to sspi on Windows for the same reason. Also document the runtime log path (/Users/Shared/infinidream.ai/Logs/) in AGENTS.md. Related: #556 will eventually supersede this by removing ffmpeg's TLS dependency entirely (use libcurl for all network). Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
scottdraves
added a commit
that referenced
this pull request
May 11, 2026
* Fix cross-platform compilation bugs (Mac-safe)
Ten standalone bug fixes that are correct on all platforms. Each was a
latent bug on macOS masked by libc++/GLUT/Metal; they surface as hard
errors on Linux/libstdc++/Vulkan.
- Common/SmartPtr.h: guard _LIBCPP_INLINE_VISIBILITY — libstdc++ does
not define _LIBCPP_HIDE_FROM_ABI, so the macro expansion failed to
compile on GCC.
- Common/BlockingQueue.h: condition_variable::wait() requires a lock
object, not a raw mutex. Three call sites passed m_mutex directly
(undefined behaviour). Also mark condition var members mutable so
const methods can legally call wait().
- Common/XTimer.h: remove unused <X11/Xlib.h> / <X11/Xutil.h> —
these headers define the None macro (0L) which clashes with
enum class TransitionType { None }. Also make Time() const to
satisfy the ITimer pure-virtual signature.
- Client/FrameDisplay.h: guard <CoreVideo/CVPixelBuffer.h> inside
#ifdef MAC — CoreVideo does not exist on Linux.
- Client/StringFormat.cpp: add missing #include <cstdarg> for
va_list / va_start / va_end.
- Client/client.h: wrap SHAREDIR in std::string() when calling
Set("settings.app.InstallDir", ...). SHAREDIR is const char*; without
the cast, overload resolution picks Set(string_view, bool) (non-null
pointer → true) instead of Set(string_view, string_view), storing a
boolean in JSON and crashing later at as_string().
- ContentDecoder/ContentDecoder.cpp: avcodec_close() was removed in
FFmpeg 6.x. Replace with avcodec_free_context() which also nulls the
pointer.
- ContentDownloader/PlaylistManager.h: add missing <condition_variable>
and <mutex> for the std::condition_variable / std::mutex members.
- DisplayOutput/Renderer/TextureFlat.h: wrap FFmpeg headers in
extern "C". Without it, sws_getContext gets C++ name mangling and
fails to link even with -lswscale present.
- Networking/EDreamClient.h: add missing SetQuota() declaration.
The method is defined in EDreamClient.cpp and called from a free
function, but was absent from the header, causing a compile error
on strict-conformance builds.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Wire Linux platform path into existing client code
Modify existing files to route Linux through Vulkan instead of falling
through to Metal (which only exists on macOS). No Mac code paths are
changed — all additions are inside new #elif defined(LINUX_GNU) or
#else branches that were previously absent or broken.
- Client/Player.cpp: change bare #else after WIN32 guard to
#elif defined(MAC) for Metal includes, add new #else block that
includes DisplayVulkan.h / RendererVulkan.h. AddDisplay() gains a
matching Linux branch that constructs CDisplayVulkan + CRendererVulkan.
Remove dead EndFrameUpdate() FPS-capping code (spFD / m_PlayerFps
undefined on Linux; the block was never reachable on Mac either due
to the surrounding #ifndef USE_METAL guard).
- Client/main.cpp: remove <GL/gl.h> / <GL/glut.h> includes from the
Linux branch (Vulkan does not use GLUT). Guard glutInit() inside
#if defined(MAC) so it is not called on Linux.
- Client/client_linux.h: remove #include "lua_playlist.h" (file does
not exist). Add #include "PlatformUtils.h". Fix m_AppData path to
~/.config/infinidream/. Derive m_WorkingDir from
PlatformUtils::GetWorkingDir() rather than the autotools SHAREDIR
macro. Fix g_Player().AddDisplay() missing nullptr second argument.
Remove g_Player().Framerate() call (method no longer exists). Fix
CElectricSheep::Update() call to pass required int argument. Replace
invalid static_cast<spCKeyEvent> with std::static_pointer_cast.
Remove entire stale voting block (m_pVoter, GetCurrentPlayingID,
RepeatSheep, m_spSplashPos/Neg — all removed from current codebase).
- Client/cpu_usage_linux.h: replace glibtop (GNOME library, requires
libgtop2 which is not a standard dependency) with direct /proc/stat
parsing. ReadProcStat() uses fscanf with a format string that matches
the literal "cpu" prefix — no throwaway variables, no string
allocation, returns matched == 4 on success. GetNumCores() uses
sysconf(_SC_NPROCESSORS_ONLN) instead of parsing /proc/cpuinfo.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Add Linux build system and platform utilities
Everything needed to configure and compile the project on Linux.
No existing Mac build files are touched.
LinuxBuild/CMakeLists.txt
Standalone CMake build for Linux (mirrors MacBuild structure).
Targets: Vulkan, X11, Boost (filesystem/thread/log/log_setup/json),
FFmpeg (via pkg-config), OpenSSL, libcurl, libpng, pthreads.
Compiles GLSL shaders to SPIR-V via glslc (from Vulkan SDK or PATH)
and copies them next to the binary at POST_BUILD. Defines LINUX_GNU,
BOOST_FILESYSTEM_VERSION=3, SHAREDIR=".".
LinuxBuild/PlatformUtils_Linux.cpp
Implements the PlatformUtils static interface for Linux:
IsInternetReachable (connect to 8.8.8.8:53), GetWorkingDir / GetAppPath
(/proc/self/exe), OpenURLExternally (xdg-open), SetThreadName
(pthread_setname_np), SetCursorHidden (X11 blank cursor),
SetOnMouseMovedCallback, DispatchOnMainThread (thread-safe queue
drained on the main thread), NotifyError (stderr), CalculateFileMD5
(OpenSSL EVP — same logic as the Mac version).
LinuxBuild/PlatformUtils_Internal.h
Internal helpers shared between DisplayVulkan and PlatformUtils_Linux:
DrainMainThreadQueue(), GetMouseCallback(), GetCursorHidden().
socket.io-client-cpp/lib/linux/libsioclient{,_tls}.a
Linux ELF builds of socket.io-client-cpp. The vendored .a files in
lib/ are Mach-O universal binaries used by the Xcode project and are
left untouched. Linux links against the lib/linux/ variants via CMake.
To rebuild: clone socket.io-client-cpp, cmake -DUSE_TLS=1, make.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Add Vulkan rendering backend for Linux
New DisplayOutput/Vulkan/ directory implements the CDisplayOutput and
CRenderer interfaces for Linux using Vulkan + X11. The Metal backend
(DisplayOutput/Metal/) is untouched.
DisplayVulkan (.h/.cpp)
Creates an X11 Window and a VkSurfaceKHR via VK_KHR_xlib_surface.
Manages VkInstance, VkDevice (picks first discrete GPU, falls back to
integrated), VkSwapchainKHR, render pass, framebuffers, and per-frame
sync primitives (semaphores + fence). Fullscreen via EWMH
_NET_WM_STATE_FULLSCREEN. Handles ConfigureNotify resize by
recreating the swapchain. XScreensaver mode: if XSCREENSAVER_WINDOW
env var is set the window is reparented into it rather than created
standalone. Implements CDisplayOutput: Initialize, Resize, SetTitle,
SetFullScreen, Present, SwapBuffers, ProcessEvents.
RendererVulkan (.h/.cpp)
Implements CRenderer. Allocates a VkDescriptorPool, descriptor set
layout, and a graphics pipeline backed by the compiled quad shaders.
Per-frame: acquires swapchain image, begins render pass, binds
pipeline + descriptor set, draws the fullscreen quad, ends pass,
submits, presents. BeginFrame/EndFrame bracket each rendered frame.
NewTextureFlat() returns a CTextureFlatVulkan.
TextureFlatVulkan (.h/.cpp)
Implements CTextureFlat. Allocates a VkImage + VkImageView + VkSampler
and a host-visible VkDeviceMemory staging buffer. Upload(spCImage)
copies RGBA pixel data via vkMapMemory then transitions the image to
SHADER_READ_ONLY_OPTIMAL. BindFrame(spCVideoFrame) maps decoded AVFrame
data directly into the staging buffer each frame for zero-copy video
upload. The descriptor set is updated with vkUpdateDescriptorSets so
the fragment shader samples the current frame.
ShaderVulkan (.h/.cpp)
Loads SPIR-V bytecode (compiled from shaders/quad.vert / quad.frag at
build time by glslc). Creates VkShaderModule.
FontVulkan (.h/.cpp)
Stub implementing CFont. Text rendering is not yet wired up on Linux;
the stub satisfies the interface so the binary links and runs.
shaders/quad.vert
Fullscreen triangle-pair. Passes UV coordinates to the fragment stage.
shaders/quad.frag
Samples a combined image sampler (the current video frame texture)
and writes to the swapchain image. YUV→RGB conversion is handled
upstream by FFmpeg swscale (frames arrive as RGBA); the shader is a
straight passthrough blit.
Verified on Arch Linux, RTX 4090, Vulkan 1.4.341, driver 575.57.08:
cmake -B build -DCMAKE_BUILD_TYPE=Debug && cmake --build build
./build/infinidream → window opens, content decoder and downloader
initialise, video playback begins.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Add native Wayland surface support (VK_KHR_wayland_surface)
At runtime, if WAYLAND_DISPLAY is set and XSCREENSAVER_WINDOW is not,
DisplayVulkan connects natively to the Wayland compositor using
VK_KHR_wayland_surface instead of VK_KHR_xlib_surface. XScreensaver
embed mode always uses X11 (that protocol is inherently X11). On
X11-only systems or if wayland-client is absent at build time, behaviour
is identical to before.
CMakeLists.txt:
Optionally find wayland-client, wayland-protocols, and wayland-scanner
via pkg-config. When all three are present, generates xdg-shell
protocol bindings (xdg-shell-protocol.c / xdg-shell-client-protocol.h)
at configure time via wayland-scanner, adds HAVE_WAYLAND compile
definition, and links wayland-client. Graceful fallback to X11-only
if any piece is missing.
DisplayVulkan.h / .cpp:
createVulkanInstance() picks VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME or
VK_KHR_XLIB_SURFACE_EXTENSION_NAME based on m_bWayland.
initWayland() — connects to wl_display, binds wl_compositor and
xdg_wm_base from the registry, creates wl_surface, xdg_surface, and
xdg_toplevel, handles ping/configure/close via static listener
callbacks (onXdgWmBasePing, onXdgSurfaceConfigure,
onXdgToplevelConfigure, onXdgToplevelClose), sets fullscreen if
requested, and does two wl_display_roundtrips to complete the initial
configure handshake before returning.
checkEvents() dispatches Wayland events with wl_display_flush() +
wl_display_dispatch_pending() instead of XPending/XNextEvent.
setFullScreen() calls xdg_toplevel_set_fullscreen / _unset_fullscreen
on Wayland; EWMH ClientMessage on X11.
Title() calls xdg_toplevel_set_title on Wayland; XStoreName on X11.
destroyWayland() tears down xdg_toplevel → xdg_surface → wl_surface
→ xdg_wm_base → wl_compositor → wl_display in dependency order,
after Vulkan surface/instance are already destroyed.
client_linux.h:
Replace CElectricSheep::Update(0) (now requires two boost::barrier
refs) with the equivalent direct calls: BeginFrameUpdate(),
DoRealFrameUpdate(0), EndFrameUpdate().
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Fix string_view passed to printf %s in ParsePlaylist (Linux crash)
EDreamClient::ParsePlaylist line 1631 passed a std::string_view to a
%s variadic argument. On Apple Clang/libc++ this accidentally works
because the ABI passes the pointer field first and it happens to be
null-terminated; on GCC/libstdc++ vsnprintf reads the struct bytes
differently and segfaults.
Fix: uuid.empty() ? "default playlist" : uuid.data()
uuid.data() is safe here — callers always pass a std::string-backed
view so the data pointer is null-terminated.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Fix Linux video playback: frame format, texture binding, shader coords
- Frame.h: set m_pFrame->format/width/height in first constructor (was
left as AV_PIX_FMT_NONE=-1, causing sws_getContext to crash)
- Clip.cpp: use AV_PIX_FMT_RGBA on Linux so ContentDecoder pre-converts
decoded frames; call BindFrame via USE_HW_ACCELERATION||LINUX_GNU guard
- TextureFlatVulkan: add Bind() override to set descriptor set on renderer;
add dirty flag so Apply() re-binds after each BindFrame upload; fast-path
RGBA upload without redundant swscale pass
- RendererVulkan: Apply() was a no-op stub — delegate to base class so
texture Bind()/Dirty() logic actually runs
- quad.vert: input coords are normalized [0,1], not pixels — remove
division by screenWidth/Height that squashed quad to a 1px strip
- websocketpp/constants.hpp: bump max_header_size 16KB→64KB for Heroku
large set-cookie response headers
- libsioclient_tls.a: rebuild with patched websocketpp header
- client.h: fix Run() loop and add virtual Update() base
- EDreamClient.cpp: fix string_view passed to %s (UB on GCC)
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Remove no-op stub comments and dead tmplog markers
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Remove legacy autotools build system and dead screensaver wrapper scripts
The Mac build (primary platform) uses Xcode/CMake and is unaffected.
These files were remnants of the original Electric Sheep Linux autotools era:
- electricsheep-saver, electricsheep-saver-gnome: wrapper scripts pointing
at an 'electricsheep' binary that no longer exists. Linux xscreensaver
integration already works via the XSCREENSAVER_WINDOW env var in
DisplayVulkan — no wrapper script needed.
- Makefile.am (root, Client/, MSVC/SettingsGUI/), configure.ac, Makefile.in:
dead autotools scaffolding superseded by LinuxBuild/CMakeLists.txt.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Reduce Linux CPU usage: vsync via FIFO present mode + FpsCap
Two targeted fixes for the high CPU usage observed on Linux (~57% CPU
for simple video playback).
RendererVulkan: switch swapchain from MAILBOX to FIFO present mode.
MAILBOX never blocks — vkQueuePresentKHR returns immediately and the
render loop spins at uncapped speed consuming a full CPU core. FIFO
is guaranteed supported by the Vulkan spec and blocks on each present
until the next vblank, giving vsync-throttled output for free with
zero extra code. Mac is unaffected (Vulkan backend is Linux-only).
client.h / Player.h: call FpsCap(m_PerceptualFPS) in the Run() loop
after each frame. FpsCap() already existed in Player.cpp (complete
with its own wall-clock timer) but was unreachable — it was buried
inside a WIN32-only private section. Move it to public and call it
from Run(), which caps frame delivery to the configured perceptual
FPS (default 20 fps) and sleeps away any remaining frame budget.
Run() is only entered from main.cpp on Linux; the Mac Cocoa/display-
link loop never calls it, so Mac behaviour is unchanged.
Together these changes eliminate the busy-spin that was burning ~30-40%
of a CPU core between frames and the uncapped GPU submission loop on
top.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Add API key authentication for Linux / headless environments
The existing auth flow only knew how to refresh a WorkOS sealed session
(wos-session cookie). On Linux there is no UI to obtain one, so a fresh
install could never authenticate.
The backend middleware already accepts an Api-Key <key> header as an
alternative to the session cookie on all protected endpoints, so no
server changes are needed.
Changes:
EDreamClient: AppendAuthHeader()
Centralises all request auth in one place. Previously every call site
duplicated three lines of get-setting / build-header / append-header.
Now: sealed session present → Cookie: wos-session=<session> (existing
behaviour); no session but api_key present → Api-Key <key>; neither →
no auth header (request will 401, existing error handling applies).
All ~15 call sites replaced with AppendAuthHeader(spDownload).
EDreamClient: SignInWithApiKey()
Persists the API key to settings.content.api_key and returns true.
No round-trip to the server needed — the key is used directly on each
subsequent request.
EDreamClient: Authenticate() fallback
After sealed-session refresh fails, checks the INFINIDREAM_API_KEY
environment variable. If set, calls SignInWithApiKey() and persists
the key for future runs. Falls back to a key already stored in
settings. This means Linux users can authenticate with:
export INFINIDREAM_API_KEY=<key> ./infinidream
or by adding settings.content.api_key to ~/.electricsheep/settings.json.
WebSocket connection
ConnectRemoteControlSocket() now passes Api-Key in the query map when
no sealed session is available, matching the HTTP auth fallback.
Mac is unaffected: EDreamClient is shared but the Mac flow always
obtains a sealed session via the first-time setup UI before reaching
any of these paths.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Fix control-reaches-end-of-non-void-function warning in Player.cpp
The streaming-load lambda (detached thread that fetches a download link
and starts a clip) declared a bool return type via an early 'return false'
on the no-display-units error path, but fell off the end without returning
on the success path. Add 'return true' after the clip-start block.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Fix black screen and white square on Linux startup
Three related issues with the startup/loading screen on Linux:
client.h: startup screen invisible during buffering
The render block was gated on (drawNoSheepIntro || drawn). When a clip
is in buffering mode g_Player().Update() returns false (drawn=false),
and if the user is logged in HasStarted() is true so drawNoSheepIntro
is also false. Result: nothing rendered at all — pure black screen while
waiting for the first frames to decode. Fix: hoist the startup-screen
visibility check into a 'showStartup' bool and include it in the outer
gate condition so the startup screen renders independently of whether
the player has a frame ready to draw.
StartupScreen.h: white square when logo.png not found
CImage::Create() initialises the 256×256 buffer to white. If Load()
fails (file not found) the blank white image was still uploaded as a
texture and rendered as a white square in the centre of the screen.
Fix: check the return value of Load() and set m_spImageRef = nullptr on
failure. The existing if (m_spImageRef) guard around the DrawQuad then
cleanly skips the logo without affecting the text rendering below it.
CMakeLists.txt: deploy logo.png next to the binary at build time
The startup screen looks for logo.png relative to the working directory
(settings.app.InstallDir). On Linux this is the build output directory,
but the asset was never copied there. Add a POST_BUILD custom command
that copies Runtime/logo.png next to the infinidream binary so it is
found on first launch without manual installation steps.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Fix startup screen hidden when player has no frames to draw yet
HasStarted() returns true as soon as the playlist is set in the startup
thread, which happens before the first render frame. This meant
drawNoSheepIntro=false and m_StartupScreen was never created, so
showStartup=false and drawn=false → pure black screen.
Fix: include !drawn in the showStartup condition so the startup screen
is shown whenever there is no video frame available yet (buffering,
quota exhausted, no content downloaded, etc.) regardless of whether
HasStarted() returned true.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Fix Linux video playback: handle Vulkan swapchain invalidation
On Wayland, vkAcquireNextImageKHR returns VK_ERROR_OUT_OF_DATE_KHR
after the first few frames during initial surface configuration.
Previously BeginFrame() returned false without recreating the swapchain,
causing BeginDisplayFrame() to return false every subsequent frame.
Since Player::Update() is gated on BeginDisplayFrame(), it was never
called, so Clip::Update() never ran, the buffering threshold was never
checked, the frame queue filled to max (25 frames), and the decoder
thread blocked on push() — meaning video never played.
Fix: store the VkSurfaceKHR in Initialize(), implement recreateSwapchain()
(wait idle → destroy framebuffers/imageviews/swapchain → recreate), and
call it from both BeginFrame() and EndFrame() on OUT_OF_DATE or SUBOPTIMAL.
Also:
- Return bool from RenderFrame() so Update() can report whether it drew
- Fix SHAREDIR path suffix (\"./\" instead of \".\") in CMakeLists.txt
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Linux Vulkan: fullscreen toggle, VAAPI PTS fix, font rendering, and misc fixes
Fullscreen / windowed toggle (Wayland):
- Add F key binding to toggle fullscreen (replaces Ctrl+F) in client_linux.h
- Add key-release guard (m_bPressed check) to prevent double-fire on toggle actions
- Add ToggleFullscreen() virtual to DisplayOutput base; override in CDisplayVulkan
- Set m_bFullScreen = bFullscreen in initWayland before the initial roundtrip so
the configure-event filter correctly accepts the startup fullscreen configure
- Parse XDG_TOPLEVEL_STATE_FULLSCREEN from the wl_array in onXdgToplevelConfigure
and ignore stale fullscreen configures when we have already requested windowed mode
- Set m_Width/m_Height = 1280x720 in setFullScreen(false) before unset_fullscreen
so RendererVulkan recreates the swapchain at the correct windowed size
- Re-assert ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE on windowed transition
- Add proactive swapchain recreation in BeginFrame when display dimensions change
(Wayland compositors do not always send VK_ERROR_OUT_OF_DATE_KHR for client-driven
resizes)
- Add xdg-decoration-unstable-v1 protocol support (server-side window borders);
falls back gracefully when the compositor does not advertise the interface (GNOME)
- Log all Wayland registry globals at startup for diagnostics
- Update CMakeLists.txt to generate xdg-decoration protocol bindings via
wayland-scanner alongside the existing xdg-shell bindings
VAAPI / video decoder fixes:
- Fix VAAPI PTS loss: av_hwframe_transfer_data copies only pixel data; manually
copy pts, pkt_dts, and best_effort_timestamp to sw_frame before av_frame_move_ref
- Guard against corrupted/wrapped last_played_frame resume values (e.g. uint32_t
wrap from a previous VAAPI PTS bug) by clamping seekFrame to a sane range
Font / HUD rendering (FontVulkan):
- Implement FreeType-based glyph atlas for Vulkan (CFontVulkan)
- Wire up TextureFlatVulkan for font atlas texture upload
Startup / display:
- Fix startup screen visibility: show logo until the first video frame is ready
- Silence spurious PNG warnings for Mac-only OSD assets missing on Linux by
removing the Warning log from the file-not-found path in LoadPNG.cpp
HUD / help text (client.h):
- Capitalise all F1 help text entries ("A: Slower playback" not "a: slower…")
- Show "F: Toggle full screen" on Linux instead of "Ctrl+F: Toggle full screen"
README: update Linux build and feature documentation
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Fix Mac build regressions introduced in previous commit
- client.h: make BK() macro a no-op on non-Linux builds; the \x01/\x02
inline-bold markers are only handled by the Linux HUD renderer — on Mac
they would appear as raw control characters in the F1 help overlay
- ContentDecoder.cpp: change #ifndef WIN32 guards to #ifdef LINUX_GNU so
the VAAPI code (vaapi_get_format, hw device init, hw frame transfer)
is only compiled on Linux; Mac retains its VideoToolbox path via the
existing USE_HW_ACCELERATION / USE_METAL logic in base.h
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Linux/Vulkan: replace FreeType text rendering with ImGui (Mac untouched)
Remove the FreeType-based CFontVulkan/CTextVulkan implementation and replace
it with ImGui-backed CFontImGui/CTextImGui, using ImGui's embedded ProggyForever
font (MIT licensed, no external font files required).
New build dependency: Dear ImGui added as a git submodule at
client_generic/imgui (pinned to v1.92.6, the latest stable release).
Its source files are compiled directly into the Linux build — no system
package or vcpkg entry needed.
- Drop FreeType dependency from LinuxBuild/CMakeLists.txt
- CFontImGui: registers font with ImGui atlas via AddFontDefaultVector()
- CTextImGui: GetExtent() measures via CalcTextSizeA()
- RendererVulkan: integrate ImGui frame lifecycle (NewFrame/Render/RenderDrawData)
- DrawText: segment-based renderer handles \n (newlines) and \t (tab stops at
4×space width); \x01/\x02 bold markers are stripped — ProggyForever has no
bold variant so bold text support is removed for now pending a future decision
on font strategy
- Remove Lato-Regular.ttf from the build (was missing its license)
- Update README: remove freetype2 from prereqs, note ImGui submodule init
No Mac files were modified. The Metal renderer, Mac CMakeLists, OSD,
and CI workflow are all unchanged.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Linux/Vulkan: fix fullscreen, HUD layout, help text, and auth robustness
X11 fullscreen / window management:
- Create window at requested size and apply _NET_WM_STATE_FULLSCREEN as a
window *property* before mapping (not a client message), so the WM
resizes it to the correct monitor dimensions on startup.
- MapNotify wait loop now captures ConfigureNotify events so the initial
fullscreen size is known before creating the Vulkan surface/swapchain.
- Add 500 ms fallback poll if ConfigureNotify arrives after MapNotify.
- Fix EWMH setFullScreen message: data.l[0] must be 0/1, not an Atom
value; set data.l[2]=0, data.l[3]=1 (source: normal application).
- checkEvents(): update m_Width/m_Height on ConfigureNotify so HUD
coordinates stay in sync with WM-driven window resizes at runtime.
- Add IsWayland() accessor to CDisplayVulkan.
Swapchain / HUD aspect ratio:
- createSwapchain(): use std::clamp(requested, min, max) instead of
caps.currentExtent, which can lag behind ConfigureNotify on X11.
- BeginFrame(): trigger swapchain recreation when Display()->Width/Height()
differs from m_swapExtent, replacing the surface-caps query that had
the same lag problem.
- Set io.DisplaySize from Display()->Width/Height() so ImGui always
reflects the true window dimensions.
- Remove max(1.0f, ...) floor from font scaling in DrawText, GetExtent,
StatsConsole, and StartupScreen; use proportional screenH/1080 scaling.
- Compute startup logo aspect ratio dynamically each frame rather than
baking it in the constructor, fixing logo squash after fullscreen toggle.
F1 help overlay:
- Remove inline bold markers (\x01/\x02) from BK macro — ProggyForever
does not support bold; simplify DrawText and GetExtent accordingly.
- Fix tab stop counts so all right-column key bindings align correctly.
Auth:
- On InvalidSession refresh failure, probe the QUOTA endpoint before
wiping the session; HTTP 200 means the token is still live and the
client proceeds logged in rather than forcing an unnecessary re-login.
- Companion backend change: e-dream-ai/backend#407
Misc: remove unused boost::bind include from Player.cpp.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Linux/Vulkan: fix ghost texture artefact on F1/F2 HUD background
CRendererVulkan::Reset() was a complete no-op, so calling it with
eTexture never cleared m_aspSelectedTextures[]. Apply() then re-bound
the stale video/startup texture, causing DrawSoftQuad to sample it
instead of the white descriptor set — manifesting as a ghost ellipse
behind the F1 help and F2 status overlays.
Fix: delegate to CRenderer::Reset(_flags) so the base class clears
m_aspSelectedTextures, then explicitly reset m_currentDescSet to
m_whiteDescSet when eTexture is requested.
Inspired by upstream commit 29a5da8 (e-dream-ai/client), which fixed
the same class of stale-texture bug on Metal by clearing stale bindings
between draw calls that share a single render encoder.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Linux: headless auth via magic link, --cached offline mode, XDG config path
- Add LoginWithMagicLinkCode(): on first run prompts for email (saved to
settings.generator.nickname), sends a one-time code, reads it from stdin,
and exchanges it for a sealed session before the window opens. Subsequent
runs auto-refresh the session; re-prompts interactively if it expires.
- Add --cached flag: skips auth entirely and plays locally cached videos in
offline mode, reporting count and size ("cycling through N (X.X GB) of
cached videos"). Exits with a clear message if the cache is empty.
- Pre-check auth state before the display window opens: if no sealed session
and no API key, attempt magic link login or abort with actionable guidance
rather than opening a window that cannot download any content.
- Store api_key and user email in settings.json (settings.content.api_key /
settings.generator.nickname) rather than a separate credentials file.
- Fix Linux settings path: remove hardcoded ~/.electricsheep/ in InitStorage()
so settings, logs, and content all live under ~/.config/infinidream/ as
client_linux.h always intended.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Print user email less often during TTY login flow
* Reduce client idle CPU by caching frame-loop diagnostics
The Linux client was doing too much synchronous work on the main/render loop for what should be a mostly idle video screensaver workload. In particular, the shared client frame path was repeatedly probing internet reachability, rebuilding cache statistics, polling download/network status, and updating large HUD/stat blocks every frame. On Linux that showed up as excessive CPU usage even when hardware video decode was active, and it also created extra event-pump churn because the Linux wrapper called Display()->Update() a second time each frame.
This change introduces a cached RuntimeDiagnostics layer inside CElectricSheep so the expensive shared-loop diagnostics are sampled on coarse timers instead of per frame. Fast-changing values such as CPU, GPU, and transfer status are refreshed at a short interval, while slower values such as internet reachability, disk/update status, and cache size are refreshed at longer intervals. The dream stats and credits HUD updates are also gated on HUD visibility so hidden overlays no longer pay the full per-frame formatting and data collection cost. An optional INFINIDREAM_PERF_LOG path remains available for coarse runtime measurements.
On Linux specifically, the extra Display()->Update() call in CElectricSheep_Linux::Update() is removed so window events are pumped once per frame through the shared render path instead of twice. That reduces unnecessary X11/Wayland work without changing presentation semantics.
This is intentionally safe for macOS because it does not change the Metal renderer, macOS display update path, swap/present behavior, or decode pipeline. The shared-code changes only reduce how often diagnostic state is recomputed and how often hidden HUDs are updated. Visible HUD behavior remains intact, user-triggered network checks still force a fresh connectivity probe, and the Linux-only event-pump change is isolated to client_linux.h.
* Add libdecor fallback for Wayland window decorations
Wayland windowed mode previously relied entirely on xdg-decoration server-side decorations. On compositors that do not provide that protocol, the Linux client came up undecorated, which left the window difficult to move and resize compared with the existing X11 path.
Add an optional libdecor-0 fallback in the Vulkan display backend and Linux build. When xdg-decoration is unavailable, the Wayland path now creates a libdecor frame, routes title/fullscreen updates through it, dispatches libdecor events during the frame loop, and tears it down safely without affecting the X11 path.
Also add Wayland cursor-theme handling for the content surface so the app restores a normal arrow when re-entered from another application, reports a distro-correct warning when libdecor decorations cannot be provided, and exposes a content-side resize hotzone near the window edges and corners to make resizing practical even when the decoration backend's own hit targets are narrow.
This change is Linux-only. macOS is unaffected because the code paths are guarded behind the Wayland/Linux build configuration and do not alter the shared Metal or Cocoa client behavior.
* Fix post-merge regressions: cross-platform safety and startup screen text
After merging upstream/master, resolve several issues introduced during
conflict resolution:
- Guard POSIX-only code in EDreamClient.cpp (#include <unistd.h>,
LoginWithMagicLinkCode body) so Windows builds are not broken
- Guard the Linux headless auth block in CElectricSheep::Startup() with
#ifdef LINUX_GNU so Mac/Windows first-run startup is not short-circuited
before the GUI auth flow can run
- Restore null guards on g_Player().Renderer() and g_Player().Display()
in StartupScreen constructor and CElectricSheep::Run()
- Remove DrawSoftQuad override keyword from RendererVulkan (upstream
removed the base class virtual in commit 1b4735d)
- Fix Frame.h constructor assigning _width/_height to AVFrame fields
- Fix duplicate ToggleFullscreen in DisplayOutput.h (bool vs void return)
- Restore startup screen text rendering: draw "Connecting to
infinidream.ai..." centered at top of screen via GetExtent() + DrawText
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Fix Mac crash: restore VideoToolbox hardware decoding in ContentDecoder
Our earlier work replaced the upstream `if (USE_HW_ACCELERATION)` block
with a `#ifdef LINUX_GNU` VAAPI block, which inadvertently deleted the
Mac VideoToolbox initialisation. Without it, FFmpeg outputs software
YUV frames. TextureFlatMetal::GetPixelBuffer() casts data[3] directly
to CVPixelBufferRef; for software frames data[3] is null, causing an
immediate crash the moment the first video starts playing. Once the
app crashes the main loop stops running and ProcessCommandQueue() is
never called, which is why remote-control commands also appeared broken.
Fix:
- Add a vt_get_format() callback (MAC-only, mirrors the existing
vaapi_get_format for Linux) so the codec negotiates
AV_PIX_FMT_VIDEOTOOLBOX rather than falling back to software YUV.
- Restore VideoToolbox hw-device creation in ContentDecoder::Open()
using av_hwdevice_ctx_create() (the correct one-step API, replacing
the upstream's fragile alloc+init pattern) guarded with
#elif defined(MAC).
The Linux VAAPI path is untouched; Windows gets neither block and
continues with software decoding as before.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Fix ffmpeg HTTPS streaming on Mac/Linux; keep Windows on Schannel
PR #541 bumped the vcpkg submodule past upstream commit b94ab47c99
("[ffmpeg] Remove deprecated securetransport"), which silently dropped
the implicit --enable-securetransport on macOS/iOS. The Apr 16 rebuild
produced libavformat.a with no TLS backend (no ff_openssl,
ff_securetransport, or ff_gnutls symbols), breaking the
Player::PlayDreamNow uncached-streaming path with:
FFmpeg warning: https or dtls protocol not found
Failed to open URL https://...
Enable the openssl feature for ffmpeg on !windows (Mac reads
/etc/ssl/cert.pem, Linux reads the distro bundle; OpenSSL 3.6.1 is
already linked for libcurl since 823d072). Leave Windows on the
portfile's default --enable-schannel, which reads the Windows cert
store natively; vcpkg's curl[ssl] port already defaults to sspi on
Windows for the same reason.
Also document the runtime log path (/Users/Shared/infinidream.ai/Logs/)
in AGENTS.md.
Related: #556 will eventually supersede this by removing ffmpeg's
TLS dependency entirely (use libcurl for all network).
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
* F2 overlay: update server/download status every frame
Timecode already refreshed per-frame but server/download status was on the
0.5s RefreshFastDiagnostics cache. Moved both into the dreamStatsVisible
block so they tick at frame rate when the overlay is visible and not at
all when it isn't.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
* Refresh Mac vcpkg cache to enable ffmpeg HTTPS streaming
The cache/univ-osx artifacts committed in a5ac6b3 predate the
ffmpeg openssl feature added in 1d998a4, so the universal libs
shipped without TLS-dependent protocols (tls, dtls, https, rtmps,
gophers, rtmp[e|s|te|ts], ffrtmpcrypt). Streaming uncached dreams
on Mac failed with "https or dtls protocol not found".
Re-run lipo_dir_merge.py against the per-triplet vcpkg trees to
pick up the openssl-enabled ffmpeg.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
* Fix Api-Key header format and add Ctrl+R/B keyboard shortcuts on Linux
- EDreamClient: fix malformed Api-Key HTTP header (missing colon).
curl_slist_append expects "Name: Value" — the missing colon meant the
header was never delivered, causing all API-key-only logins to silently
fail and return a black screen.
- client_linux.h: honour Ctrl modifier on KEY_R and KEY_B. Ctrl+R opens
the remote control URL and Ctrl+B opens the playlists page in the
browser (mirroring the Mac NSMenu handlers in ESWindow.mm). Without
this check both keys triggered their unmodified actions (Repeat /
Report) regardless of Ctrl state.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Fix Windows build: namespace, ToggleFullscreen void return, AddDisplay signature
- Add DisplayOutput:: namespace to CDisplayDX11 construction/cast sites (Player.cpp, RendererDX11.cpp)
- Change ToggleFullscreen() from bool to void; callers now check IsFullscreen() before/after
- Update AddDisplay() call sites in client_win32.h to pass nullptr for new middle parameter
- Add cachedOnlyMode=false stub in WinMain (--cached flag is Linux-only for now)
- Bump generated build version header to 0.1.0 / 6fe1bb1
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
* Fix Windows render rate: scope FpsCap call to Linux
Commit e0a87d5 added FpsCap(m_PerceptualFPS) to the Run() loop to fix
Linux CPU usage, claiming "Run() is only entered from main.cpp on
Linux." That is incorrect: WinMain in main.cpp also calls client.Run(),
so the cap was throttling the Windows render loop to the perceptual FPS,
slowing it down and producing visibly choppy motion.
Guard the FpsCap call with #ifdef LINUX_GNU. Windows is paced by DXGI
Present and does not need an explicit cap; Mac never enters Run() (uses
the Cocoa/display-link loop) and is unaffected either way.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
* Remove startup splash text and simplify StartupScreen
Drop the "Connecting to infinidream.ai..." message and all the font/text
plumbing it required. The text was invisible on macOS anyway (CATextLayer
starts hidden and nothing unhid it), and it adds nothing useful on the
platforms where it did render. Also clean up dead members
(m_LogoSize, m_TextureUploaded, m_MoveMessageCounter) and the orphaned
m_bServerMessageStartTimer block, plus the dead drawNoSheepIntro branch
in client.h.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
* Fix Remote indicator flash at startup
Force live connectivity probes until the first websocket connection, and
tighten the cache interval from 3s to 0.5s. The diagnostics-caching commit
widened the auth-done -> websocket-up gap from sub-frame to up to 3
seconds, triggering the "initial connection not yet established" branch
before the cache caught up.
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
* Fix Linux link order: move OpenSSL after libsioclient_tls.a
ld --as-needed dropped libssl before the socket.io static archive could
reference it, failing with "DSO missing from command line".
Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
---------
Co-authored-by: amillionbouncyballs <[email protected]>
Co-authored-by: Claude Sonnet 4.6 <[email protected]>
Co-authored-by: alansley <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.