Repository navigation
port(linux): 2.0 engine settings and status against the Linux engine (Phase B2) - #86
Merged
Merged
Conversation
…gine 2.0's playback-device picker ran `FTHRclips --list-playback-devices` with subprocess.CREATE_NO_WINDOW, which does not exist on Linux, so the scan died with an AttributeError the worker did not catch, and the chosen endpoint was then forced to '' for argv[24] on every non-Windows launch. The Linux engine (#82) answers the same flag with PulseAudio sinks in the same schema and captures `<sink>.monitor` from argv[24]. Run the scan with the host library environment instead of the Windows flag, pass the saved sink to the engine, and label the default entry and the fallback hint for what the Linux engine does (default output when the sink is missing at start). Selecting a device restarts capture through the existing audio_capture_changed path, as on Windows. Windows text and flags are unchanged.
argv[6] is a diagnostic raw-frame figure to the Windows engine, which is why the UI derives it from width x height x fps and caps it at 2 GB. The Linux engine enforces it as the byte budget of its compressed ring (#82), so a 2.0 buffer of up to 900 s at a normal bitrate was silently cut to whatever 2 GB covers: about 5 minutes at 50 Mbps. On Linux pass a budget from bitrate x (buffer + 5 s) with 25% headroom for VBR peaks, within the engine's 64..16384 MB range and never above half of physical memory; the engine logs when that still cannot cover the whole buffer. Windows keeps the old figure.
The 2.0 encoder list only offers backends whose one-frame probe succeeds. On Linux the AMD entry probed h264_amf, which needs AMD's proprietary AMF runtime, so AMD and Intel machines saw only Automatic and Software even though the engine's AMD preference (argv[17] = 2) opens VA-API first. On Linux probe VA-API (with a hwupload filter on the engine's render node, FTHR_VAAPI_DEVICE or renderD128) and AMF under the same key and label it "VA-API (AMD / Intel)", run probes with the host library environment so a frozen build's ffmpeg can load the VA-API driver, and bump the Linux cache version so old device profiles are re-probed. Windows backends, labels and cache version are unchanged.
2.0 looks only for ffmpeg.exe/ffprobe.exe and dropped the Linux bundle and source-tree locations, so a Linux build never found its own LGPL ffmpeg and fell back to whatever ffmpeg is on PATH (or none). The UI needs it to mix the Python microphone track into saved clips and to probe encoders. Restore the platform executable names, the beside-the-executable layout and FTHRcapture_linux/third_party/ffmpeg.
2.0's "Downmix stereo microphone to mono" sets argv[25] for the Windows engine's native microphone capture. On Linux the engine captures no microphone (argv[25] is ignored, #82) and the UI records it through core/mic_recorder.py, which always opens a single channel, so a stereo microphone is already downmixed and the switch did nothing. Show it checked and disabled with that reason instead of offering a no-op setting; Windows keeps the working control.
Three status paths read wrong against the Linux engine: - The engine answers the focus-pause STOP_RECORDING with ACTIVE|PAUSED, which capture health maps to DEGRADED, so one poll after "PAUSED - GAME UNFOCUSED" the status bar claimed "CAPTURE DEGRADED". Show the pause while the engine reports it. - After a terminal capture failure the Linux engine publishes BACKEND_FAILED with its reason, waits 2 s and exits 0. The 2.0 UI then added "exited unexpectedly (code 0)". Say that the engine stopped after the failure already shown; crashes and non-zero exits keep the old text. - With no engine process left, the status poll replaced ENGINE STOPPED with CONNECTING although nothing would ever be connected to. Keep ENGINE STOPPED until the user restarts capture. All three are gated to non-Windows; Windows status text is unchanged.
Playback-sink listing without CREATE_NO_WINDOW and with the host environment, sink selection and its unavailable fallback label, the always-mono microphone control, the VA-API probe (and an unchanged Windows probe), the focus-pause and engine-exit status helpers, and the Linux ffmpeg lookup.
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.
Phase B2 of the 2.0 catch-up (
docs/linux-2.0-catch-up.md), narrowed to the 2.0 UI driving the Linux engine from #82. Windows behaviour is unchanged: every change is either gated to non-Windows or only touches Linux-only code.What changes
FTHRclips --list-playback-deviceswithsubprocess.CREATE_NO_WINDOW. That flag does not exist on Linux, so the scan died with an uncaught AttributeError. On top of that, argv[24] was forced to''. Now the scan runs with the host library environment, the chosen PulseAudio sink goes to argv[24], and the labels say "System default" and "default output". Changing the device restarts capture through the existingaudio_capture_changedpath.h264_amf, so AMD and Intel machines only saw Automatic and Software. It now probes VA-API (with hwupload onFTHR_VAAPI_DEVICE/renderD128) and then AMF, under the key the engine maps to VA-API (argv[17] = 2). The entry is labelled "VA-API (AMD / Intel)". Probes run with the host environment, and the Linux cache version is bumped so old profiles are probed again.ffmpeg/ffprobe), the frozen layout andFTHRcapture_linux/third_party/ffmpeg. 2.0 only looked forffmpeg.exe, so it fell back to whatever ffmpeg was on PATH. The UI uses this ffmpeg to mix in the mic track and to probe encoders.core/mic_recorder.pyalways records one channel and the engine ignores argv[25]. The 2.0 downmix switch is therefore shown checked and disabled, with that reason.PAUSED — GAME UNFOCUSED.Already handled on
linux-2.0and checked here without code changes: manual recording stays off on Linux (#83),RECONFIGURE_REQUIREDrestarts are Windows-only, monitor validation takes the Linux output-name path, focus pause sends STOP/START_RECORDING with an empty resume string, and the custom clip-length actions (save_custom_clip_<n>) route through the hotkey socket.Verification
Launch: the engine was built from this branch against the pinned FFmpeg. The app ran with a throwaway HOME and XDG_RUNTIME_DIR,
HYPRLAND_INSTANCE_SIGNATUREunset and no session bus, on Hyprland with wlr-screencopy and an AMD GPU. A small driver drove the real settings widgets, and saves went through the hotkey socket. ffprobe results:save_clip(normal 10 s)h264_vaapi,encoder_pref=0save_custom_clip_20encoder_pref=4,Using: libopenh264, UI "Encoding active: libopenh264", no HARDWARE ENCODING UNAVAILABLEencoder_pref=2→h264_vaapi;encoder_pref=0→ NVENC tried,h264_vaapiplayback=easyeffects_sink,-> easyeffects_sink.monitor; then<default>Buffer=900s,Byte budget 15595 MiB, engine warns ~654 s coverage (half-RAM cap)HARDWARE ENCODING UNAVAILABLE, backend reason "No video encoder could be opened", then ENGINE STOPPED "stopped after the capture failure above", status stays ENGINE STOPPED; RESTART back to Auto captures againPAUSED — GAME UNFOCUSED, then CAPTURINGTests, run file by file under an isolated HOME:
test_capture_backend_detection. Itstest_binary_existsnow passes because an engine is built in the tree. Its other 3 tests fail only because that binary needsLD_LIBRARY_PATHset to the pinned FFmpeg; with it set, 4/4 pass.test_game_detection_popupsegfaults under offscreen Qt both before and after.tests/test_linux_engine_settings.py, plus Linux cases intest_engine_error_recovery.py(argv[6]/[17]/[23]/[24], no creationflags) andtest_capture_settings_policy.py(ring budget).ruff check .passes.tools/verify_exception_handling.pyreports 83 silent handlers, baseline 92.Deferred / out of scope (per maintainer scope change)
CAPTURE_UNAVAILABLE: The configured monitor returned an empty screenshot, because QScreen cannot grab on Wayland. Restoring the grim / Screenshot-portal path fromlinuxis a separate PR. This does not affect clip capture or saving.tools/qualify_alpha_stability.py. It passes Windowscreationflagson Linux (test_strict_probe_requires_audio_when_requested). It lives in tools/, which PR Phase D: packaging, release gates and CI for the 2.0 catch-up #84 owns.test_camera_provider_failures,test_linux_camera_refresh.test_game_detector,test_foreground_game_detector.test_wayland_screenshot_portal,test_screenshot_save.test_encoder_capabilitiesexpects a Linux capture-card checkbox that 2.0 removed,test_design_overhaul_repairs,test_settings_managerdefaults.test_capture_settings_popup: Windows monitor-path cases run without pinning the platform.test_asset_license_gate,test_qt_license_gate(PR Phase D: packaging, release gates and CI for the 2.0 catch-up #84).test_clip_viewer_p1_gate,test_alpha_ui_truthlegacy crop, andtest_windows_troubleshooting_docs(the docs script fails under node).