Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
d8ee5fb
Prepare 1.7.1 release metadata
btsouth Sep 7, 2026
491c975
Track play sessions across emulators with omakade-sessiond
btsouth Sep 7, 2026
033ca9e
Show release, platform, genres, credits, and background for identifie…
btsouth Sep 7, 2026
2a04a3e
Fix session accounting and improve game details
btsouth Sep 8, 2026
f49b390
Preserve downloaded covers and recover missing source artwork
btsouth Sep 8, 2026
b9a3021
Prioritize game details and review metadata presentation
btsouth Sep 8, 2026
bd83e33
Merge branch 'codex/cover-preservation-local' into codex/feature-qual…
btsouth Sep 8, 2026
e3e2a20
Contain navigation focus and test real detail controls
btsouth Sep 8, 2026
538ff90
Fix session attribution and surface persistence failures
btsouth Sep 8, 2026
4caca09
Harden matching, backups, artwork, and playtime
btsouth Sep 8, 2026
62d6ce7
Show regional release dates and title evidence
btsouth Sep 8, 2026
0b0b219
Add genre decade and platform discovery filters
btsouth Sep 8, 2026
c6898e6
Add optional Home view and persistent Up next queue
btsouth Sep 8, 2026
537a0c3
Prevent cover flashing during background metadata updates
btsouth Sep 8, 2026
a0ebc14
Improve detail backgrounds and resolve crowded catalog searches
btsouth Sep 8, 2026
7cce527
Organize navigation and menus for local controller testing
btsouth Sep 8, 2026
528fcb6
Fix popup keyboard navigation and balance game actions
btsouth Sep 8, 2026
da69bf7
Rebuild Home with cover tiles and personal library discovery
btsouth Sep 8, 2026
73f5651
Fix Home layout collapse when opened after startup
btsouth Sep 8, 2026
6c82061
Smooth Home mouse wheel scrolling without delaying other input
btsouth Sep 8, 2026
fd39460
Preserve wheel velocity across consecutive Home scroll events
btsouth Sep 8, 2026
20c8b20
Avoid full-library Home rebuilds during background updates
btsouth Sep 8, 2026
48f3d4f
Avoid redundant artwork and filter updates during metadata refresh
btsouth Sep 8, 2026
bc9cccf
Use consistent full-width actions across popup menus
btsouth Sep 8, 2026
bbee641
Prioritize identity activity and launch controls in game details
btsouth Sep 8, 2026
0c3686c
Polish game details and separate identification tools
btsouth Sep 8, 2026
9276616
Keep game refresh state separate from background IGDB work
btsouth Sep 8, 2026
28bd08b
Unify game artwork controls and recover covers through verified aliases
btsouth Sep 8, 2026
d427c3c
Keep artwork panel within the window with a fixed Done header
btsouth Sep 8, 2026
d33f849
Polish cover selection panel and late-loading tile navigation
btsouth Sep 8, 2026
957d84c
Bound rating tooltips and reconcile the 1.8 candidate
btsouth Sep 8, 2026
0a288bc
Prevent overlapping library cards after returning from details
btsouth Sep 8, 2026
0e4bee7
Prioritize games and direct play on Home
btsouth Sep 8, 2026
c989a73
Preserve library cards during unchanged startup scans
btsouth Sep 8, 2026
d2d2e41
Add launch feedback and restore Home action focus
btsouth Sep 9, 2026
5ba99e6
Clarify session recording and verify full Home queues
btsouth Sep 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ jobs:
jq . /tmp/omakade-vulnerabilities.json
test "$(jq length /tmp/omakade-vulnerabilities.json)" -eq 0
- name: Scan package SBOM
# Arch advisories are a baseline for ARM64, not complete Arch Linux ARM coverage.
env:
GRYPE_DISTRO: arch:rolling
uses: anchore/scan-action@27805bf3b4e84b4a5c980df22ed233c00390a439 # v7.4.2
with:
sbom: omakade-${{ env.VERSION }}-${{ matrix.arch }}.spdx.json
Expand Down
27 changes: 27 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
# Changelog

## 1.8.0

- Add optional Home, persistent Up Next, and suggestions from the local library.
Improve Home wheel scrolling during background metadata updates.
Put game shelves before shortcuts and add direct Play beside Details.
- Filter by genre, decade, and platform, including saved filters.
- Show regional release dates, title evidence, genres, credits, and descriptions.
Preserve manual identity choices and leave ambiguous matches correctable.
- Bring matching and cover selection together under Game & Artwork. Preserve
existing portraits during refresh and cache maintenance, and recover covers
through verified aliases. Keep Done visible while the panel scrolls.
- Prevent overlapping desktop library captions after returning from a game.
Keep existing cards stable during unchanged startup console scans.
- Improve popup keyboard navigation, controller focus, and narrow details layouts.
Restore the original Home action after closing details. Show immediate launch
feedback, suppress repeated presses briefly, and keep launch errors visible.
Limit the rating-count tooltip to the rating and put credits before regional details.
- Add optional local session recording for configured emulator process profiles.
Show recorder status and separate imported time from recorded time. New installs
opt in; existing recording preferences and history are preserved.
Attribution requires a recognizable game path in process arguments. Internal
emulator game changes and wrapper handoffs still need adapter-specific testing.
- Back up explicit metadata choices, recorded sessions, baselines, and preferences
in archive format 2. Format 1 remains readable. Emulator saves are excluded.
- Report persistence failures and protect referenced artwork during cache cleanup.
- Keep ROM Folders on the Sources overview. Fixes #40.

## 1.7.0

Omakade 1.7 brings console libraries, more ways to organize your games, and a
Expand Down
59 changes: 58 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 3.24)

project(Omakade VERSION 1.7.0 LANGUAGES C CXX)
project(Omakade VERSION 1.8.0 LANGUAGES C CXX)

find_package(PkgConfig REQUIRED)
find_package(OpenSSL REQUIRED COMPONENTS Crypto)
Expand Down Expand Up @@ -57,6 +57,43 @@ if(OMAKADE_IDLE_INHIBIT AND NOT TARGET Qt6::GuiPrivate)
endif()
qt_standard_project_setup(REQUIRES 6.8)

# Play session tracking, shared by the Omakade window and the omakade-sessiond
# recorder. Kept separate so the daemon links only Qt Core, Sql, and Network.
add_library(omakade_tracking STATIC
src/tracking/AppNotify.cpp
src/tracking/AppNotify.h
src/tracking/PlaySessionStore.cpp
src/tracking/PlaySessionStore.h
src/tracking/ProcFs.cpp
src/tracking/ProcFs.h
src/tracking/ProcessMatcher.cpp
src/tracking/ProcessMatcher.h
src/tracking/SessionDatabase.cpp
src/tracking/SessionDatabase.h
src/tracking/SessionRecorder.cpp
src/tracking/SessionRecorder.h
)

target_include_directories(omakade_tracking PUBLIC src)
target_link_libraries(omakade_tracking PUBLIC
Qt6::Core
Qt6::Network
Qt6::Sql
)

if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
target_compile_options(omakade_tracking PRIVATE -Wall -Wextra -Wpedantic)
endif()

qt_add_executable(omakade-sessiond src/sessiond/main.cpp)
target_compile_definitions(omakade-sessiond PRIVATE
OMAKADE_SESSIOND_PROFILES="${CMAKE_INSTALL_FULL_DATADIR}/omakade/sessiond-profiles.json"
)
target_link_libraries(omakade-sessiond PRIVATE omakade_tracking)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
target_compile_options(omakade-sessiond PRIVATE -Wall -Wextra -Wpedantic)
endif()

add_library(omakade_core STATIC
src/backup/BackupArchive.cpp
src/backup/BackupArchive.h
Expand Down Expand Up @@ -92,6 +129,8 @@ add_library(omakade_core STATIC
src/input/ControllerInput.h
src/input/CouchCursorManager.cpp
src/input/CouchCursorManager.h
src/library/HomeModel.cpp
src/library/HomeModel.h
src/library/LibraryFilterModel.cpp
src/library/LibraryFilterModel.h
src/library/DatabaseTuning.h
Expand Down Expand Up @@ -187,6 +226,7 @@ add_library(omakade_core STATIC

target_include_directories(omakade_core PUBLIC src)
target_link_libraries(omakade_core PUBLIC
omakade_tracking
Qt6::Quick
PkgConfig::SDL3
PkgConfig::LIBSECRET
Expand Down Expand Up @@ -232,20 +272,24 @@ qt_add_qml_module(omakade
qml/components/FieldClearButton.qml
qml/components/CoverSizeControl.qml
qml/components/CoverArtwork.qml
qml/components/LaunchFeedback.qml
qml/components/GameCard.qml
qml/components/CouchLibraryView.qml
qml/components/CouchKeyboard.qml
qml/components/CouchBrowsePanel.qml
qml/components/GameMetadataEditor.qml
qml/components/SettingsPanel.qml
qml/components/GlassButton.qml
qml/components/ActionMenu.qml
qml/components/MenuAction.qml
qml/components/LibraryView.qml
qml/screens/ArtworkEditor.qml
qml/screens/RestoreStartup.qml
qml/screens/BackupEditor.qml
qml/screens/SavedFiltersEditor.qml
qml/screens/BulkOrganizationEditor.qml
qml/screens/ManualGameEditor.qml
qml/screens/HomeScreen.qml
qml/screens/GameDetails.qml
)

Expand Down Expand Up @@ -294,6 +338,15 @@ install(TARGETS omakade
BUNDLE DESTINATION .
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(TARGETS omakade-sessiond
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)
install(FILES resources/sessiond-profiles.json
DESTINATION ${CMAKE_INSTALL_DATADIR}/omakade
)
install(FILES packaging/omakade-sessiond.service
DESTINATION ${CMAKE_INSTALL_LIBDIR}/systemd/user
)
install(FILES packaging/io.github.tsouth89.Omakade.desktop
DESTINATION ${CMAKE_INSTALL_DATADIR}/applications
)
Expand All @@ -313,6 +366,10 @@ install(FILES README.md PRIVACY.md SUPPORT.md CHANGELOG.md docs/COMPATIBILITY.md
DESTINATION ${CMAKE_INSTALL_DATADIR}/doc/omakade
)

install(FILES docs/RECORDING-COVERAGE.md
DESTINATION ${CMAKE_INSTALL_DATADIR}/doc/omakade/docs
)

include(CTest)
if(BUILD_TESTING)
add_subdirectory(tests)
Expand Down
40 changes: 39 additions & 1 deletion PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -872,13 +872,51 @@ It preserves role IDs and names across the existing nine game models.
- Automatic fuzzy merging across stores
- Emulator installation and ROM scraping
- Plugin marketplace or third-party executable plugins
- Background daemon
- General background daemons beyond the play session recorder
- Mobile companion
- Cross-device sync

Each item needs a separate product decision. None should enter incidentally while
building the library.

## Play session tracking

Omakade shows playtime per game, but every emulator keeps its own counter in its
own format and several keep none at all. A small recorder closes that gap.

### Shipped

- `omakade-sessiond`, a per-user systemd service shipped with the package,
polls the process table every few seconds and attributes sessions by matching
a known emulator binary in the process table with a game image path on its
command line. This covers Omakade launches, terminal launches, and wrapper
scripts, including emulators Omakade has no source for, as long as the game
path is on the command line.
- Sessions land in `play_sessions` in the library database with a periodic
heartbeat. A recorder restart reconciles dead processes at their last
heartbeat so a crash never invents play time, and elapsed time comes from the
monotonic clock so suspended time is not billed.
- Sources merge their imported playtime with recorded sessions as
max(imported, baseline + sessions). New baselines include zero and subtract
already recorded sessions conservatively, since a late import may include them.
Existing baselines are preserved. Gaps in recording can leave the imported
total ahead until observed time catches up; exact overlap reconciliation is
still future work.
- A Settings toggle (on by default) controls both the display and the recorder,
which reads the same config key. When a session for an emulator whose own
playtime is written on exit ends, the recorder asks the running Omakade
window to rescan that source so its import stops going stale.

### Later

- Attribute sessions for games loaded from an emulator's own file picker, where
the command line carries no path: window-title matching through the Hyprland
IPC first, then per-emulator recents and log adapters.
- Pause the clock while the emulator window is unfocused, matching how
Ryujinx excludes paused time from its own counter.
- A settings view for recorded sessions per game.


## Decisions to settle before M0 implementation

Recommended defaults are listed first:
Expand Down
7 changes: 7 additions & 0 deletions PRIVACY.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ Omakade retains:
choices, provider IDs, ratings, and popularity scores in the same database
- Owned Steam App IDs, titles, and account playtime after an explicit library
sync in the same database
- Play sessions recorded by `omakade-sessiond` in the same database: game
paths, start and end times, and accumulated seconds. The recorder only reads
the local process table and never sends anything anywhere; sessions never
leave the machine.
- Steam ID, RetroAchievements username, public IGDB client ID, cache limit, and
reduced-motion preference, console-view overrides, and cover sizes in
`$XDG_CONFIG_HOME/omakade/config.toml`
Expand Down Expand Up @@ -58,6 +62,9 @@ A SteamGridDB API key is stored through Secret Service under
`io.github.tsouth89.Omakade.SteamGridDB`. It is never written to config,
the database, logs, or process arguments.

Recording is off for new configurations until enabled in Settings. Existing saved
choices are preserved. Disabling recording retains recorded history locally.

## Backup and restore

Export creates a local archive at the path you choose. It includes personal
Expand Down
54 changes: 46 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ into one quiet, cover-focused home that follows the active Omarchy theme.

## Features

Omakade 1.7.0 includes:
The 1.8.0 candidate includes:

- Native and Flatpak Steam, Lutris, Heroic, Faugus, RetroArch, PCSX2,
Ryujinx, Cemu, shadPS4, and Dolphin discovery, plus direct GOG installation
Expand All @@ -30,6 +30,9 @@ Omakade 1.7.0 includes:
- Console cards for cartridge and disc systems, with a per-system choice
between cards and library tiles, per-game pinning, and ROM folder scanning
for EmuDeck-style layouts
- Optional local session recording from supported emulator process arguments
- Optional Home, persistent Up Next, and local discovery suggestions
- Genre, decade, and platform filters with saved-filter persistence
- One-click details and delegated launching through the owning platform
- Omarchy palette, font, transparency, and live theme updates
- Search, favorites, hidden games, sorting, and source filters that combine,
Expand All @@ -40,7 +43,9 @@ Omakade 1.7.0 includes:
- Local Steam achievements plus optional Web API enrichment
- Optional RetroAchievements progress for supported RetroArch systems
- Optional Steam owned-library sync with installed and ready-to-install views
- Optional IGDB ratings, popularity sorting, and game-length estimates
- Optional IGDB ratings, popularity sorting, and game-length estimates, plus
release dates, original platform, genres, credits, and a background
paragraph on game details
- SteamGridDB portrait covers with per-game identification and artwork choices
- Adjustable cover size and per-console grouping preferences
- Local, downloaded, and user-selected cover, hero, and logo artwork
Expand Down Expand Up @@ -102,23 +107,23 @@ verify the package, and install it. If Omakade is already installed, `pacman -U`
upgrades it in place without removing your settings or library data:

```bash
curl -fLO https://github.com/btsouth/omakade/releases/download/v1.7.0/omakade-1.7.0-1-x86_64.pkg.tar.zst
curl -fLO https://github.com/btsouth/omakade/releases/download/v1.7.0/SHA256SUMS
curl -fLO https://github.com/btsouth/omakade/releases/download/v1.8.0/omakade-1.8.0-1-x86_64.pkg.tar.zst
curl -fLO https://github.com/btsouth/omakade/releases/download/v1.8.0/SHA256SUMS
sha256sum -c SHA256SUMS --ignore-missing
sudo pacman -U ./omakade-1.7.0-1-x86_64.pkg.tar.zst
sudo pacman -U ./omakade-1.8.0-1-x86_64.pkg.tar.zst
```

### Install or upgrade from a browser download

1. Open the [latest release](https://github.com/btsouth/omakade/releases/latest).
2. Under **Assets**, download `omakade-1.7.0-1-x86_64.pkg.tar.zst` (or
`omakade-1.7.0-1-aarch64.pkg.tar.zst` for ARM64) and `SHA256SUMS` into the same folder.
2. Under **Assets**, download `omakade-1.8.0-1-x86_64.pkg.tar.zst` (or
`omakade-1.8.0-1-aarch64.pkg.tar.zst` for ARM64) and `SHA256SUMS` into the same folder.
3. Open a terminal in that folder and run the commands below. On ARM64,
replace `x86_64` with `aarch64` in the package filename:

```bash
sha256sum -c SHA256SUMS --ignore-missing
sudo pacman -U ./omakade-1.7.0-1-x86_64.pkg.tar.zst
sudo pacman -U ./omakade-1.8.0-1-x86_64.pkg.tar.zst
```

Launch Omakade from the application launcher or run `omakade` in a terminal.
Expand Down Expand Up @@ -303,12 +308,45 @@ the preferred launch mode. Its cursor hides during controller or keyboard use,
returns on mouse movement, and remains visible in Desktop Mode. `Ctrl+M`
toggles reduced motion and `Ctrl+D` opens settings and source diagnostics.

## Track play sessions

Every emulator keeps its own playtime in its own format, and some keep none at
all. Omakade ships an optional recorder. Turn on **Record Playtime** in Settings,
then enable its service:

```bash
systemctl --user enable --now omakade-sessiond
```

The recorder watches the process table and attributes sessions by the game path
on an emulator's command line. Profiles include RetroArch, Dolphin, PCSX2, Cemu,
Ryujinx, shadPS4, and yuzu-family forks like Eden. Attribution requires a
recognizable game path in those arguments. Internal game changes and wrapper
handoffs need adapter-specific validation; profile coverage is not runtime acceptance. Emulators that
count their own time retain their imported totals. Omakade takes the larger of
the imported total and its baseline plus recorded time. Recovery preserves committed time and
excludes unobserved downtime. Late imports are treated conservatively as including
already recorded sessions; gaps in tracking can delay visible increases. Existing
history is not rewritten automatically.

New installations require opting in. Existing saved choices are preserved, and
older configuration files without this setting retain their previous enabled
default. Settings reports whether the recorder is running separately from whether
recording is enabled. The recorder continues after Omakade closes; paused emulator
time counts. Switching recording off preserves history and displays imported time.
Game details separates imported emulator time from Omakade's recorded total.

Loading a game from inside an emulator's own file picker is not counted yet,
because the command line carries no path then. See the
[recording coverage notes](docs/RECORDING-COVERAGE.md) for validation limits.

## Local data

- Library: `~/.local/share/omakade/library.sqlite3`
- Settings: `~/.config/omakade/config.toml`
- Downloaded artwork: `~/.cache/omakade/`
- Selected custom artwork: `~/.local/share/omakade/artwork/`
- Play sessions: `play_sessions` and `play_baselines` tables in the library

Core library discovery, local achievements, artwork, search, organization,
controller navigation, and launching require no Steam API key or network
Expand Down
Loading
Loading