How rafaelmardojai/blanket works
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: window.py window.py · player.py player.py · blanket.gresource.xml blanket.gresource.xml · meson.build meson build
Components 24
App Core
Startup, playback, presets, and application state.
- main.py · Application startup and wiring.
blanket/main.py - main_player.py · Player-focused startup path.
blanket/main_player.py - player.py · Central playback and mixing controller.
blanket/player.py - sound.py · Single ambient sound state and behavior.
blanket/sound.py - preset.py · Save/restore sound combinations.
blanket/preset.py - preferences.py · Application preferences and user options.
blanket/preferences.py - define.py · App-wide identifiers and metadata.
blanket/define.py
UI Layer
Main window and reusable GTK widgets.
- window.py · Main application window composition.
blanket/window.py - playpause.py · Play and pause control.
blanket/widgets/playpause.py - sound_item.py · Sound tile and item display.
blanket/widgets/sound_item.py - volume_row.py · Volume control row.
blanket/widgets/volume_row.py - preset widgets · Preset chooser, dialog, and row components.
- sound menu · Context menu and rename dialog for sounds.
blanket/widgets/sound_context_menu.py
Platform Integration
Desktop and system integration boundaries.
- settings.py · Persistent configuration access.
blanket/settings.py - mpris.py · Exposes playback through MPRIS.
blanket/mpris.py - gschema.xml · GSettings schema definition.
data/com.rafaelmardojai.Blanket.gschema.xml
Packaged Assets
Embedded UI, sounds, styling, and metadata.
- window.blp · Blueprint definition for the main window.
data/resources/window.blp - dialog blueprints · Blueprint definitions for dialogs and rows.
- sounds · Bundled ambient sound library.
data/resources/sounds - style.css · Application styling.
data/resources/style.css - blanket.gresource.xml · Compiles UI, icons, and sounds into GResource.
data/resources/blanket.gresource.xml
Build & Release
Build, packaging, localization, and distribution files.
- desktop/metainfo · Desktop entry and app metadata templates.
data/com.rafaelmardojai.Blanket.desktop.in - meson build · Build and install orchestration.
meson.build - po/ · Translated UI strings.
po
Connections 28
- 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.