# rafaelmardojai/blanket architecture

> Architecture diagram of the GitHub repository rafaelmardojai/blanket, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-05-14). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/rafaelmardojai/blanket
- Repository: https://github.com/rafaelmardojai/blanket

## Overview

1. **What this repo is**
   - Blanket is a **Python desktop application** for GNOME/GTK that plays multiple ambient sounds simultaneously.
   - The runtime stack is centered on **PyGObject + GTK4 + libadwaita**, with **GStreamer** handling audio playback.

2. **High-level composition**
   - The app is structured as a **single desktop client** with one main window and a small set of supporting dialogs/popovers.
   - There is no backend server or network service; all state and playback logic live locally inside the process.

3. **Startup and app entry points**
   - `blanket/main.py` is the likely application entry module and startup coordinator.
   - `blanket/main_player.py` suggests a player-oriented controller or bootstrap path used to wire the player model to the UI.
   - `blanket/window.py` appears to host the main shell of the app, assembling the overall UI.

4. **Core playback subsystem**
   - `blanket/player.py` is the central playback abstraction.
   - `blanket/sound.py` likely represents a single ambient sound source and its playback state.
   - This is the architectural boundary where UI actions are translated into **audio engine operations**.
   - The data flow is: user adjusts a sound or preset → player updates sound state → GStreamer plays/mixes the selected sounds.

5. **Sound library and defaults**
   - The repository bundles a fixed library of sounds under `data/resources/sounds/` such as rain, waves, storm, fireplace, etc.
   - These are application assets, not user-generated media, and they define the built-in catalog the UI presents.
   - `blanket/define.py` likely contains constants and metadata for that catalog or other app-wide identifiers.

6. **UI layer and reusable widgets**
   - Most user interaction is implemented as small GTK widgets under `blanket/widgets/`.
   - The visible UI is split into composable pieces:
     - sound tile/item rendering
     - play/pause control
     - volume control
     - sound context menu
     - preset chooser and preset row
     - rename and dialog surfaces
   - This indicates a modular presentation layer where the main window composes reusable controls rather than embedding all behavior in one file.

7. **Presets and user state**
   - `blanket/preset.py` and `blanket/preferences.py` are the main state-management pieces beyond playback.
   - Presets are likely the user-facing way to save and restore sound combinations and volume levels.
   - Preferences are separate from presets: preferences cover app behavior, while presets cover sound configurations.

8. **Settings and persistence boundary**
   - `blanket/settings.py` plus `data/com.rafaelmardojai.Blanket.gschema.xml` indicate the app uses **GSettings/dconf** for persisted configuration.
   - This is the main persistence mechanism for app settings on the desktop.
   - The architectural boundary here is important: persistent config is handled by GNOME’s settings system, not by custom files or a database.

9. **Desktop integration**
   - `blanket/mpris.py` exposes the player over **MPRIS**, which lets the desktop shell and media controls interact with playback.
   - That makes Blanket behave like a media player from the OS point of view, even though it’s playing ambient loops.
   - The MPRIS layer bridges internal player state with external desktop control surfaces.

10. **Resources, UI definition, and theming**
    - `data/resources/*.blp` contains Blueprint UI definitions for windows, dialogs, and rows.
    - `data/resources/style.css` provides app styling.
    - `data/resources/blanket.gresource.xml` and the Meson resource files show that UI, icons, and sounds are **compiled into a GResource bundle**.
    - This means the app is packaged as a self-contained GTK application with embedded assets.

11. **Packaging and build system**
    - The project uses **Meson/Ninja** for building and installing.
    - `pyproject.toml` and `uv.lock` suggest Python dependency management is also part of the repo workflow.
    - `blanket.spec`, `.desktop.in`, and `.metainfo.xml.in` show it is packaged for Linux distributions and software centers.

12. **Localization and documentation**
    - `po/` contains a large translation catalog, so the UI is fully localized.
    - `doc/Sound_documentation.md` and `SOUNDS_LICENSING.md` document asset meaning and licensing, which matters because the sounds are redistributed with the app.

13. **Useful architecture summary for a diagram**
    - The main diagram should show:
      - **GTK/libadwaita UI layer** on top
      - **widget/dialog components** in the middle
      - **player/sound/preset/settings logic** as the application core
      - **GStreamer** as the audio backend
      - **GSettings/GResource/MPRIS** as platform integration layers
      - **embedded sounds/icons/Blueprint UI files** as packaged static assets

14. **Key boundaries**
    - UI and playback are separated, but tightly coordinated.
    - Persistence is handled through GNOME-native settings rather than custom storage.
    - External integration is limited to desktop standards like MPRIS and standard Linux packaging/localization infrastructure.

Main entry points: [`blanket/window.py`](https://github.com/rafaelmardojai/blanket/blob/master/blanket/window.py) (window.py), [`blanket/player.py`](https://github.com/rafaelmardojai/blanket/blob/master/blanket/player.py) (player.py), [`data/resources/blanket.gresource.xml`](https://github.com/rafaelmardojai/blanket/blob/master/data/resources/blanket.gresource.xml) (blanket.gresource.xml), [`meson.build`](https://github.com/rafaelmardojai/blanket/blob/master/meson.build) (meson build)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_g_app["App Core"]
  node_n_main["main.py<br/>entrypoint<br/>[main.py]"]
  node_n_main_player["main_player.py<br/>bootstrap<br/>[main_player.py]"]
  node_n_player["player.py<br/>playback core<br/>[player.py]"]
  node_n_sound["sound.py<br/>sound model<br/>[sound.py]"]
  node_n_preset["preset.py<br/>preset state<br/>[preset.py]"]
  node_n_preferences["preferences.py<br/>prefs state<br/>[preferences.py]"]
  node_n_define["define.py<br/>constants<br/>[define.py]"]
end

subgraph group_g_ui["UI Layer"]
  node_n_window["window.py<br/>shell<br/>[window.py]"]
  node_n_playpause["playpause.py<br/>widget<br/>[playpause.py]"]
  node_n_sound_item["sound_item.py<br/>widget<br/>[sound_item.py]"]
  node_n_volume_row["volume_row.py<br/>widget<br/>[volume_row.py]"]
  node_n_preset_ui["preset widgets<br/>widget set"]
  node_n_sound_menu["sound menu<br/>widget"]
end

subgraph group_g_integration["Platform Integration"]
  node_n_settings["settings.py<br/>gsettings bridge<br/>[settings.py]"]
  node_n_mpris["mpris.py<br/>desktop control<br/>[mpris.py]"]
  node_n_gschema["gschema.xml<br/>settings schema"]
end

subgraph group_g_assets["Packaged Assets"]
  node_n_window_ui["window.blp<br/>blueprint ui<br/>[window.blp]"]
  node_n_blp_ui["dialog blueprints<br/>blueprint ui"]
  node_n_sounds[("sounds<br/>audio assets")]
  node_n_style["style.css<br/>theme<br/>[style.css]"]
  node_n_gresource["blanket.gresource.xml<br/>resource manifest"]
end

subgraph group_g_build["Build & Release"]
  node_n_desktop["desktop/metainfo<br/>package metadata"]
  node_n_meson["meson build<br/>build system<br/>[meson.build]"]
  node_n_po[("po/<br/>localization")]
end

node_n_main -->|"creates"| node_n_window
node_n_main -->|"initializes"| node_n_player
node_n_main_player -->|"wires"| node_n_player
node_n_window -->|"uses"| node_n_playpause
node_n_window -->|"uses"| node_n_sound_item
node_n_window -->|"uses"| node_n_volume_row
node_n_window -->|"uses"| node_n_preset_ui
node_n_window -->|"uses"| node_n_sound_menu
node_n_player -->|"manages"| node_n_sound
node_n_player -->|"loads/saves"| node_n_preset
node_n_player -->|"publishes"| node_n_mpris
node_n_sound -->|"plays"| node_n_sounds
node_n_preset -->|"persists"| node_n_settings
node_n_preferences -->|"persists"| node_n_settings
node_n_settings -->|"defined by"| node_n_gschema
node_n_window -->|"defined by"| node_n_window_ui
node_n_playpause -->|"defined by"| node_n_blp_ui
node_n_sound_item -->|"defined by"| node_n_blp_ui
node_n_preset_ui -->|"defined by"| node_n_blp_ui
node_n_sound_menu -->|"defined by"| node_n_blp_ui
node_n_gresource -->|"bundles"| node_n_window_ui
node_n_gresource -->|"bundles"| node_n_sounds
node_n_gresource -->|"bundles"| node_n_style
node_n_meson -->|"builds"| node_n_gresource
node_n_meson -->|"packages"| node_n_desktop
node_n_meson -->|"builds"| node_n_po
node_n_desktop -->|"launches"| node_n_main
node_n_define -->|"configures"| node_n_player

click node_n_main "https://github.com/rafaelmardojai/blanket/blob/master/blanket/main.py"
click node_n_main_player "https://github.com/rafaelmardojai/blanket/blob/master/blanket/main_player.py"
click node_n_window "https://github.com/rafaelmardojai/blanket/blob/master/blanket/window.py"
click node_n_player "https://github.com/rafaelmardojai/blanket/blob/master/blanket/player.py"
click node_n_sound "https://github.com/rafaelmardojai/blanket/blob/master/blanket/sound.py"
click node_n_preset "https://github.com/rafaelmardojai/blanket/blob/master/blanket/preset.py"
click node_n_preferences "https://github.com/rafaelmardojai/blanket/blob/master/blanket/preferences.py"
click node_n_settings "https://github.com/rafaelmardojai/blanket/blob/master/blanket/settings.py"
click node_n_mpris "https://github.com/rafaelmardojai/blanket/blob/master/blanket/mpris.py"
click node_n_define "https://github.com/rafaelmardojai/blanket/blob/master/blanket/define.py"
click node_n_playpause "https://github.com/rafaelmardojai/blanket/blob/master/blanket/widgets/playpause.py"
click node_n_sound_item "https://github.com/rafaelmardojai/blanket/blob/master/blanket/widgets/sound_item.py"
click node_n_volume_row "https://github.com/rafaelmardojai/blanket/blob/master/blanket/widgets/volume_row.py"
click node_n_sound_menu "https://github.com/rafaelmardojai/blanket/blob/master/blanket/widgets/sound_context_menu.py"
click node_n_window_ui "https://github.com/rafaelmardojai/blanket/blob/master/data/resources/window.blp"
click node_n_sounds "https://github.com/rafaelmardojai/blanket/tree/master/data/resources/sounds"
click node_n_style "https://github.com/rafaelmardojai/blanket/blob/master/data/resources/style.css"
click node_n_gresource "https://github.com/rafaelmardojai/blanket/blob/master/data/resources/blanket.gresource.xml"
click node_n_gschema "https://github.com/rafaelmardojai/blanket/blob/master/data/com.rafaelmardojai.Blanket.gschema.xml"
click node_n_desktop "https://github.com/rafaelmardojai/blanket/blob/master/data/com.rafaelmardojai.Blanket.desktop.in"
click node_n_meson "https://github.com/rafaelmardojai/blanket/blob/master/meson.build"
click node_n_po "https://github.com/rafaelmardojai/blanket/tree/master/po"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_n_main,node_n_main_player,node_n_player,node_n_sound,node_n_preset,node_n_preferences,node_n_define toneBlue
class node_n_window,node_n_playpause,node_n_sound_item,node_n_volume_row,node_n_preset_ui,node_n_sound_menu toneAmber
class node_n_settings,node_n_mpris,node_n_gschema toneMint
class node_n_window_ui,node_n_blp_ui,node_n_sounds,node_n_style,node_n_gresource toneRose
class node_n_desktop,node_n_meson,node_n_po toneIndigo
```

## Components

### App Core

Startup, playback, presets, and application state.

- [main.py](https://github.com/rafaelmardojai/blanket/blob/master/blanket/main.py): entrypoint · Application startup and wiring. · `blanket/main.py`
- [main_player.py](https://github.com/rafaelmardojai/blanket/blob/master/blanket/main_player.py): bootstrap · Player-focused startup path. · `blanket/main_player.py`
- [player.py](https://github.com/rafaelmardojai/blanket/blob/master/blanket/player.py): playback core · Central playback and mixing controller. · `blanket/player.py`
- [sound.py](https://github.com/rafaelmardojai/blanket/blob/master/blanket/sound.py): sound model · Single ambient sound state and behavior. · `blanket/sound.py`
- [preset.py](https://github.com/rafaelmardojai/blanket/blob/master/blanket/preset.py): preset state · Save/restore sound combinations. · `blanket/preset.py`
- [preferences.py](https://github.com/rafaelmardojai/blanket/blob/master/blanket/preferences.py): prefs state · Application preferences and user options. · `blanket/preferences.py`
- [define.py](https://github.com/rafaelmardojai/blanket/blob/master/blanket/define.py): constants · App-wide identifiers and metadata. · `blanket/define.py`

### UI Layer

Main window and reusable GTK widgets.

- [window.py](https://github.com/rafaelmardojai/blanket/blob/master/blanket/window.py): shell · Main application window composition. · `blanket/window.py`
- [playpause.py](https://github.com/rafaelmardojai/blanket/blob/master/blanket/widgets/playpause.py): widget · Play and pause control. · `blanket/widgets/playpause.py`
- [sound_item.py](https://github.com/rafaelmardojai/blanket/blob/master/blanket/widgets/sound_item.py): widget · Sound tile and item display. · `blanket/widgets/sound_item.py`
- [volume_row.py](https://github.com/rafaelmardojai/blanket/blob/master/blanket/widgets/volume_row.py): widget · Volume control row. · `blanket/widgets/volume_row.py`
- **preset widgets**: widget set · Preset chooser, dialog, and row components.
- [sound menu](https://github.com/rafaelmardojai/blanket/blob/master/blanket/widgets/sound_context_menu.py): widget · Context menu and rename dialog for sounds. · `blanket/widgets/sound_context_menu.py`

### Platform Integration

Desktop and system integration boundaries.

- [settings.py](https://github.com/rafaelmardojai/blanket/blob/master/blanket/settings.py): gsettings bridge · Persistent configuration access. · `blanket/settings.py`
- [mpris.py](https://github.com/rafaelmardojai/blanket/blob/master/blanket/mpris.py): desktop control · Exposes playback through MPRIS. · `blanket/mpris.py`
- [gschema.xml](https://github.com/rafaelmardojai/blanket/blob/master/data/com.rafaelmardojai.Blanket.gschema.xml): settings schema · GSettings schema definition. · `data/com.rafaelmardojai.Blanket.gschema.xml`

### Packaged Assets

Embedded UI, sounds, styling, and metadata.

- [window.blp](https://github.com/rafaelmardojai/blanket/blob/master/data/resources/window.blp): blueprint ui · Blueprint definition for the main window. · `data/resources/window.blp`
- **dialog blueprints**: blueprint ui · Blueprint definitions for dialogs and rows.
- [sounds](https://github.com/rafaelmardojai/blanket/tree/master/data/resources/sounds): audio assets · Bundled ambient sound library. · `data/resources/sounds`
- [style.css](https://github.com/rafaelmardojai/blanket/blob/master/data/resources/style.css): theme · Application styling. · `data/resources/style.css`
- [blanket.gresource.xml](https://github.com/rafaelmardojai/blanket/blob/master/data/resources/blanket.gresource.xml): resource manifest · Compiles UI, icons, and sounds into GResource. · `data/resources/blanket.gresource.xml`

### Build & Release

Build, packaging, localization, and distribution files.

- [desktop/metainfo](https://github.com/rafaelmardojai/blanket/blob/master/data/com.rafaelmardojai.Blanket.desktop.in): package metadata · Desktop entry and app metadata templates. · `data/com.rafaelmardojai.Blanket.desktop.in`
- [meson build](https://github.com/rafaelmardojai/blanket/blob/master/meson.build): build system · Build and install orchestration. · `meson.build`
- [po/](https://github.com/rafaelmardojai/blanket/tree/master/po): localization · Translated UI strings. · `po`

## Connections

- main.py → window.py: creates · Main entry constructs the application shell.
- main.py → player.py: initializes · Bootstraps the playback controller.
- main_player.py → player.py: wires · Player-oriented startup path.
- window.py → playpause.py: uses · Main window embeds transport controls.
- window.py → sound_item.py: uses · Main window composes sound tiles.
- window.py → volume_row.py: uses · Main window exposes volume controls.
- window.py → preset widgets: uses · Main window includes preset surfaces.
- window.py → sound menu: uses · Main window attaches sound actions.
- player.py → sound.py: manages · Playback controller operates on individual sounds.
- player.py → preset.py: loads/saves · Player coordinates preset state.
- player.py → mpris.py: publishes · Playback state is exposed to desktop controls.
- sound.py → sounds: plays · Sound model binds to bundled audio assets.
- preset.py → settings.py: persists · Preset and app state are stored via settings.
- preferences.py → settings.py: persists · User preferences are stored via settings.
- settings.py → gschema.xml: defined by · Settings keys come from the schema.
- window.py → window.blp: defined by · Main window layout is authored in Blueprint.
- playpause.py → dialog blueprints: defined by · Widget surfaces are defined in Blueprint files.
- sound_item.py → dialog blueprints: defined by · Sound item UI is authored in Blueprint.
- preset widgets → dialog blueprints: defined by · Preset-related widgets are authored in Blueprint.
- sound menu → dialog blueprints: defined by · Sound menu and rename dialog are authored in Blueprint.
- blanket.gresource.xml → window.blp: bundles · UI definitions are compiled into resources.
- blanket.gresource.xml → sounds: bundles · Audio assets are compiled into resources.
- blanket.gresource.xml → style.css: bundles · Styling is bundled with the app.
- meson build → blanket.gresource.xml: builds · Meson assembles the resource bundle.
- meson build → desktop/metainfo: packages · Build system installs desktop metadata.
- meson build → po/: builds · Localization catalogs are part of the build.
- desktop/metainfo → main.py: launches · Desktop entry starts the app.
- define.py → player.py: configures · Shared constants inform core playback behavior.
