Skip to content

Backgroundog Service

Taiizor edited this page Jun 5, 2026 · 3 revisions

Backgroundog Service

Sucrose.Backgroundog.exe is the headless, long-running background service behind Sucrose's audio-reactive and system-status APIs. It continuously collects machine telemetry (CPU, GPU, RAM, network, storage, battery, BIOS, motherboard, date) plus the now-playing audio metadata and a live FFT audio spectrum, then pushes that data to the running wallpaper over one of three interchangeable transports (Pipe, Signal, or Transmission). It also acts as the engine that enforces Sucrose's performance/pause rules — deciding when to pause, suspend, or close the wallpaper based on conditions like screen lock, full-screen apps, battery level, and CPU/GPU/RAM thresholds. This page is for developers and power users who want to understand exactly what Backgroundog does, what data it emits, and how its timing and settings work.

Contents

Role and lifecycle

Backgroundog is a console (hidden) process with a long-running loop. It is not started directly; it is launched on demand through the command bus when a wallpaper needs it:

✔Backgroundog✖<path-to-Sucrose.Backgroundog.exe>

The Launcher/engine spawns it (via Commandog) when PerformanceCounter is enabled, before the engine itself starts.

Startup sequence (App.Main):

  1. SSDHG.Configure() (high-performance GPU) + SSDHR.Configure() (private runtime), UTF-8 console encoding, set thread culture from the Culture setting.
  2. Single-instance guard: Instance.Basic(Mutex.Backgroundog, App.Backgroundog) — the global mutex {Sucrose-Wallpaper-Engine-Backgroundog} plus a WorkCount <= 1 check (see Single-Instance & Mutexes).
  3. Security.Apply().
  4. Initialize.Start(), then the loop: do { Initialize.Dispose(); await Task.Delay(AppTime = 1000 ms); } while (Exit).
  5. On stop: Initialize.Stop().

Internal.Exit defaults to true. When there is no live wallpaper after a retry sequence, Attempt.Start() sets Exit = false and the service terminates itself — Backgroundog never lingers without a wallpaper to feed.

flowchart TD
    Cmd["Commandog: ✔Backgroundog✖&lt;path&gt;"] --> Gate{"Instance.Basic<br/>single-instance gate"}
    Gate -->|already running| Stop1["exit"]
    Gate -->|first instance| Init["Initialize.Start()"]
    Init --> Loop["Loop: AppTime = 1000 ms<br/>InitializeTimer tick = 100 ms"]
    Loop --> Spec["Specification.Start()<br/>collect all sensors"]
    Spec --> Pick{"live wallpaper?"}
    Pick -->|"running, not paused"| Perf["Performance.Start()<br/>should a rule trip?"]
    Pick -->|"paused / closed"| Cond["Condition.Start()<br/>should it resume?"]
    Pick -->|none| Attempt["Attempt.Start()<br/>retry Run() up to 5x"]
    Attempt -->|nothing starts| Exit["Exit = false<br/>service self-terminates"]
    Perf --> Loop
    Cond --> Loop
Loading

Timers and timing constants

All timing constants live in Manage/Internal.cs (milliseconds):

Constant Value Meaning
AppTime 1000 Outer loop delay.
InitializeTime 100 Base tick unit; the InitializeTimer fires every 100 ms.
InitializeDueTime 3000 (100 × 30) Delay before the first tick.
SpecificationLessTime 1000 Cadence for light sensors.
SpecificationTime 2000 Cadence for standard sensors.
SpecificationMaxTime 3000 Re-entrancy cool-down for the heavy pass.
SpecificationPeakTime 10000 Cadence for expensive sensors (e.g. storage WMI).

Each tick (Initialize.InitializeTimer_Callback):

  1. Specification.Start() — collect all sensors as fire-and-forget tasks.
  2. If a Processing re-entrancy flag allows it, run exactly one of:
    • Performance.Start() — when a live wallpaper is running and not already paused (checks whether a rule should trip).
    • Condition.Start() — when already paused/closed (checks whether to resume).
    • Attempt.Start() — when there is no live wallpaper.

A Processing flag ensures only one heavy pass runs at a time, then waits SpecificationMaxTime.

Sensor collection

Specification.Start() launches each sensor in its own Task.Run, guarded by a per-sensor boolean flag (e.g. BiosManagement, PingManagement, AudioManagement, ProcessorManagement2, GraphicManagement2, NetworkManagement2, StorageManagement2, etc.) so a slow sensor never blocks the rest.

Sensor Source Notes
BIOS WMI Win32_BIOS Name, Caption, Version, Description, ReleaseDate, Manufacturer, SerialNumber, CurrentLanguage. One-shot.
Date DateTime.Now Refreshed every tick.
Ping Skylark.Standard.Extension.Ping Host chosen by the PingType setting (default "Bing"); 1000 ms timeout. Only when online (Network.GetHostEntryAsync).
Audio NPSMLib + WASAPI Only when AudioRequired is on. See the two sections below.
Memory GlobalMemoryStatusEx (Skylark.Wing) Physical + virtual (page file) in GB; MemoryLoad %.
Battery WMI Win32_Battery + Skylark.Wing.Utility.Power AC status, energy saver, life %, power plan.
Graphic VorticeAdapterEnumerator (DXGI) + "GPU Engine" perf counters Adapter list persisted to the GraphicInterfaces system setting; first adapter auto-selected; usage read by LUID and clamped to 0–100.
Network Network.InstanceNetworkInterfaces() + "Network Interface" perf counters Interface list persisted to NetworkInterfaces; first auto-selected; "Bytes Sent/sec" & "Bytes Received/sec" → Upload/Download/Total.
Storage WMI Win32_LogicalDisk + "LogicalDisk"/"PhysicalDisk" perf counters Collected on the slow (SpecificationPeakTime, 10 s) cadence.
CPU WMI Win32_Processor + "Processor / % Processor Time" perf counters _Total and per-core (0..ProcessorCount-1); builds the Cores array with min/max flags.
Motherboard WMI Win32_BaseBoard Product, Version, Manufacturer; Name = "<Manufacturer> <Product>".
Remote / Virtual / FullScreen / Focus Skylark.Wing helpers Collected only when the matching performance rule is non-Resume (or already active).

Perfomance-counter collection is gated by the PerformanceCounter setting (default true).

Audio visualizer (FFT)

The audio spectrum is produced by Extension/AudioVisualizer.cs and only runs when AudioRequired is on.

  • Capture: NAudio.Wave.WasapiLoopbackCapture records the system output ("what you hear"). The class implements IMMNotificationClient and recreates the capture when the default render device changes (OnDefaultDeviceChanged for DataFlow.Render).
  • Pipeline per DataAvailable buffer:
    1. Wrap in a WaveBuffer, taking length FloatBuffer.Length / 8.
    2. Build a Complex[] and run an FFT via MathNet.Numerics.IntegralTransforms.Fourier.Forward (FourierOptions.Default).
    3. Keep the last VerticalSmoothness = 2 FFT frames; produce MaxSample = 128 output bins.
    4. Smooth with HorizontalSmoothness = 1 plus a multi-frame average → a double[128] magnitude array.
    5. Fire AudioDataAvailable, storing the array into AudioData.Data.

The result is the 128-sample spectrum exposed to web wallpapers as Audio.DataData[0] is approximately the bass band, and an all-zero array means silence. Libraries: NAudio, MathNet.Numerics. See Audio API for the JavaScript side.

Now-playing metadata

Extension/AudioSession.cs uses NPSMLib (NowPlayingSessionManager / MediaPlaybackDataSource). On SessionListChanged it reads:

  • MediaObjectInfo — Title, Artist, Subtitle, AlbumTitle, AlbumArtist, TrackNumber, AlbumTrackCount, MediaType.
  • MediaPlaybackInfo — RepeatMode, PlaybackRate/Mode/State, ShuffleEnabled, PropsValid, LastPlayingFileTime, SourceAppId.
  • MediaTimelineProperties — EndTime, Position, StartTime, Min/MaxSeekTime, PositionSetFileTime (times reported in TotalMilliseconds).
  • A thumbnail stream, Base64-encoded into AudioData.ThumbnailString.

AudioData.State indicates whether a media session currently exists.

Output channels and the JSON payload

After collection, Specification.Start() builds a single payload of 10 JObject fields and pushes it over whichever channel(s) are enabled. All channels are gated on !Condition (data is not sent while the wallpaper is paused/closed).

Channel Enabled when Target
Pipe PipeRequired BackgroundogManager.StartClient(json) → pipe "Sucrose.Wallpaper.Engine.Backgroundog.Pipe".
Signal SignalRequired BackgroundogManager.FileSave<…>(…) → writes Backgroundog-<guid>.sgnl under %AppData%\Sucrose\Cache\SignalT.
Transmission TransmissionRequired TCP to Loopback:TransmissionPort. Default transport.

The active transport is selected by the CommunicationType setting (default Transmission) on the engine side; the producer reads the *Required/TransmissionPort flags the engine sets. The payload is JSON-serialized with Newtonsoft (Formatting.None, TypeNameHandling.None). Only the WebView and CefSharp engines consume this channel (#if LIVE_WEBVIEW || LIVE_CEFSHARP). See IPC for the full transport mechanics.

flowchart LR
    Spec["Specification.Start()<br/>builds 10-JObject payload<br/>Bios/Date/Audio/Memory/Battery/<br/>Graphic/Network/Storage/Processor/Motherboard"]
    Spec -->|PipeRequired| Pipe["StartClient(json)<br/>Backgroundog.Pipe"]
    Spec -->|SignalRequired| Signal["FileSave<br/>Backgroundog-&lt;guid&gt;.sgnl"]
    Spec -->|TransmissionRequired| Trans["TCP loopback<br/>: TransmissionPort"]
    Pipe --> Web["WebView / CefSharp<br/>Web.cs server"]
    Signal --> Web
    Trans --> Web
    Web --> Exec["Compatible hooks<br/>ExecuteScriptAsync"]
    Exec --> JS["Wallpaper JS<br/>SucroseAudioData / Sucrose&lt;X&gt;Data"]
Loading

The data contract (field reference)

The 10 JObjects (Pipe.Interface.Backgroundog) are: Bios, Date, Audio, Memory, Battery, Graphic, Network, Storage, Processor, Motherboard. Their inner field names (from Extension/Data.cs) are the public data contract for wallpaper authors:

Object Fields
Bios Name, State, Caption, Version, Description, ReleaseDate, Manufacturer, SerialNumber, CurrentLanguage
Date Day, Hour, Year, Month, State, Minute, Second, Kind, DayOfYear, Millisecond, DayOfWeek
Audio State, Title, Artist, Subtitle, AlbumTitle, Data, AlbumArtist, SourceAppId, TrackNumber, MediaType, PlaybackRate, PropsValid, RepeatMode, ShuffleEnabled, PlaybackMode, AlbumTrackCount, ThumbnailString, PlaybackState, EndTime, Position, StartTime, LastPlayingFileTime, PositionSetFileTime, MaxSeekTime, MinSeekTime
Memory Name, State, MemoryLoad, MemoryUsed, VirtualName, MemoryAvailable, VirtualMemoryLoad, VirtualMemoryUsed, VirtualMemoryAvailable
Battery Name, State, Status, Chemistry, SavingMode, BatteryFlag, Description, LifePercent, SaverStatus, FullLifetime, ACPowerStatus, DesignVoltage, LifeRemaining, ChargeStatus, BatteryLifeTime, PowerPlanType, EstimatedRunTime, EnergySaverType, PowerLineStatus, BatteryLifePercent, BatteryFullLifeTime, EstimatedChargeRemaining
Graphic Max, Min, Now, Name, State, Manufacturer
Network Host, Name, Ping, State, Total, Online, Upload, Download, PingData, TotalData, UploadData, PingAddress, DownloadData, FormatTotalData, FormatUploadData, FormatDownloadData
Storage State, Drivers, LogicalDrivers, PhysicalDrivers (each a JArray of disks)
Processor Max, Min, Now, Core, Name, Type, Cores, State, Thread, CoresMax, CoresMin, CoresNow, ProcessorCount
Motherboard Name, State, Product, Version, Manufacturer

Every object carries a State boolean indicating whether its data is valid for the current tick. The Audio.Data field is the 128-sample FFT spectrum described above. For the JavaScript-side shape of these objects, see System API and Audio API.

Settings

Backgroundog reads its configuration from the Backgroundog settings store. Keys, defaults, and clamp ranges:

Setting Default Range / Type Effect
AudioRequired false bool Enable audio capture + FFT visualizer.
PipeRequired false bool Enable Pipe output.
SignalRequired false bool Enable Signal output.
TransmissionRequired false bool Enable TCP (Transmission) output.
TransmissionPort 0 0–65535 Loopback port (set dynamically at engine start).
CommunicationType Transmission Pipe / Signal / Transmission Active live-data transport.
PerformanceCounter true bool Enable perf-counter sensors + start Backgroundog with the wallpaper.
PingType "Bing" string (host key) Host used for the network ping.
PingValue 100 0–1000 (ms) Ping threshold for the Network performance rule.
UploadValue 800 0–99999999 Upload threshold.
UploadType Kilobyte Skylark.Enum.StorageType Upload threshold unit.
DownloadValue 10 0–99999999 Download threshold.
DownloadType Megabyte StorageType Download threshold unit.
ProcessorUsage 70 0–100 (%) CPU pause threshold.
GraphicUsage 70 0–100 (%) GPU pause threshold.
MemoryUsage 80 0–100 (%) RAM pause threshold.
BatteryUsage 50 0–100 (%) Battery pause threshold.
NetworkAdapter "" string Selected network adapter (auto-selected).
GraphicAdapter "" string Selected GPU adapter (auto-selected).
PausePerformance / ClosePerformance false bool Transient state flags written by the service.

The per-trigger performance modes (LockPerformance, SleepPerformance, BatteryPerformance, etc.) and PausePerformanceType are surfaced on the Settings → Performance page. See Performance Rules for what each rule does.

Performance / pause enforcement

Backgroundog owns the auto-pause logic. Performance.Start() evaluates rules in this fixed order:

Lock → Focus → Sleep → Memory → Remote → Battery → Console →
Graphic → Network → Session → Virtual → Processor → FullScreen →
ScreenSaver → BatterySaver

Each rule is skipped if its mode is Resume. Otherwise the service polls the condition for a rule-specific MaxCount (instant 0 for Lock/Sleep/Console/Session/ScreenSaver; 5 for most others; threshold-based for Memory/Graphic/CPU/Battery/Network). On a trip it sets the CategoryPerformance, sets Condition = true, and calls Lifecycle():

  • Mode Close → set ClosePerformance, call Live.Helper.Kill.Stop() (close the wallpaper).
  • Mode Pause → set PausePerformance. If PausePerformanceType.Heavy, the live process is suspended (via Space.Extension.Lifecycle.Suspend), including WebView2/CefSharp child processes whose command line contains "Sucrose" and the Aurora application process. Light pauses without suspending threads.

In both cases the Launcher tray icon is notified over Signal (Icon = true).

Condition.Start() is the mirror: while in a category it polls until the condition clears, then resumes — Close restarts the wallpaper (Run.Start()), Pause/Heavy resumes the process (Lifecycle.Resume(...)), and Condition is cleared. Tray icon Signal Icon = false.

Attempt.Start() runs when there is no live wallpaper: it retries Space.Helper.Live.Run() up to 5 times (1 s apart, 3 s settle on success). If nothing starts, it sets Exit = false, clears the two transient pause flags, and the service stops.

The enum values behind these rules (src/Shared/Sucrose.Shared.Dependency/Enum/PerformanceType.cs):

  • PerformanceType: Close, Pause, Resume.
  • PausePerformanceType: Heavy, Light.
  • NetworkPerformanceType: Not, Ping, Upload, Download.
  • CategoryPerformanceType: Not, Lock, Focus, Sleep, Memory, Remote, Battery, Console, Graphic, Network, Session, Virtual, Processor, FullScreen, ScreenSaver, BatterySaver.
  • HighPerformanceType: Default, PowerSaving, HighPerformance.

Windows session listener

Extension/WindowsListener.cs implements Skylark.Wing.Interface.IEventListener and feeds session events into the performance engine:

  • OnLogon / OnLogoffWindowsSession.
  • OnDisplayLock / OnDisplayUnlockWindowsLock.
  • OnStartScreenSaver / OnStopScreenSaverWindowsScreenSaver.

It is started/stopped by Extension/Windows.cs (Start() / Stop()).

See also

  • IPC — the three live-data transports and the command bus that carry Backgroundog's data.
  • Performance Rules — user-facing explanation of every auto-pause/close condition.
  • Create Audio API — how a web wallpaper subscribes to the audio spectrum and now-playing data.
  • Create System API — the JavaScript shape of the system-status objects.
  • Architecture Overview — where Backgroundog sits in the process roster.

Home

Getting Started

Wallpaper Types

Using Sucrose

Settings Reference

Creating Wallpapers

Engine Reference

Automation & Command Line

Architecture & Internals

Data, Files & Diagnostics

Building & Contributing

Help & Support

Clone this wiki locally