Introduce plugin system support (done right)#8
Open
Toni500github wants to merge 40 commits into
Open
Conversation
The old Makefile and mk/common.mk rules had no header dependency tracking (no -MMD/-MP), so editing imgui.h during the 1.92.9 WIP migration didn't trigger a rebuild of liboshot_imgui.so. The result was a stale .so linked against fresh app code, with mismatched ImGuiIO layouts between the two. This is what IMGUI_CHECKVERSION() caught as an assertion failure in debug builds, and very likely also explains the earlier "toolbar click resets selection" bug, since ui_blocks_selection()/HandleSelectionInput() are unchanged between the working and broken commits. CMakeLists.txt already builds the same targets with proper compiler- driven dependency tracking and never showed either symptom. All CI already builds via CMake, so there's no remaining reason to keep a second, manually-synced build description around. Replace the root Makefile with a thin wrapper around `cmake --build`, keeping the existing CLI (make, clean, distclean, dist, DEBUG=0/1 -> build/release or build/debug). mk/common.mk and the per-lib Makefiles under src/libs/ are now deleted. Keeping it on a separate commit in case I want to roll this back.
g_api was a single global struct, so with more than one plugin loaded, config reads/writes and log lines could get misattributed to whichever plugin last touched it. Replace it with plugin_runtime_t, one instance per loaded plugin, keyed by a unique id in g_plugins. ScopedActivePlugin (RAII) sets g_current_plugin around every call into plugin code (init, render, on_ocr_done, destroy), so host-side oshot_* calls always resolve against the correct plugin, including reentrant calls. Also: - oshot_get_abi_version() now returns the host's constant instead of echoing back the active plugin's own version - config lookups now key off plugin id (unique) instead of display name (not guaranteed unique), fixing a settings collision between same-named plugins; ImGui PushID switched to id for the same reason - plugin id/name are validated at load time; duplicate ids are rejected instead of silently overwriting the existing entry - init() now runs after the runtime entry exists and is scoped active, so config reads during init() see correct values - on_ocr_done now receives a real result struct (text, confidence, psm) instead of requiring a re-fetch through the text-buffer side channel; allocated once per call and freed once, not leaked per plugin - plugin_entry_t / g_plugin_entries removed; shutdown destroy() now happens via plugin_runtime_t's destructor
also separate some plugins code away from screenshot_tool.cpp to plugins.cpp
let's avoid annoying the user sometimes
hope this fixes all macos and windows builds 😭
…ow() also some CMakeLists.txt improvements
finally pushed this damn commit :wilted_rose:
Each plugin now gets its own TomlAPI-backed config.toml, loaded at plugin load and persisted via the new SaveFile() after on_save_preferences commits changes. Plugins can still manage their own file/format via oshot_get_plugin_data_dir().
also make `mk_cache_entries` constexpr and array for, "perfomances"
Avoid full rebuilds by preserving the generated version header when unchanged and fix its CMake dependency tracking.
it was expensive plus forgot to check if the dir existed so it was kinda crashing
this kinda sucks and needs to be created a manifest standard ASAP
from sizeof(oshot_plugin_t) == 88 to 80
also don't bleed the combo list with error color
Ported from cufetchpm (customfetch) because apparently
reinventing a package manager for every project I write is now a
personality trait. And because starting a new codebase sucks ass.
Adds a new oshotpm/ subtree with a shared lib (oshot_plugman) and
its executable (oshotpm), wired into CMakeLists.txt behind the
existing DISABLE_PLUGINS switch.
Manifest format (oshot-plugin.toml) so far:
- repo: name, git url, tracked git-hash
- plugins[]: name, id, description, output_dir, licenses,
authors, build_steps, platforms
- top-level dependencies list (declared, not consumed yet)
Management commands wired up in main.cpp:
install, update, list [-v], enable/disable, uninstall,
gen-manifest, help. Install accepts either a repo url/path
(clone + build) or a local directory already on disk.
State tracking:
- StateManager persists installed repos/plugins to an
auto-generated TOML state file
- enable/disable works by renaming built libraries to/from a
.disabled suffix, which is delightfully hacky and also fine
Still missing / rough edges:
- is_valid_name() is referenced in manifest.hpp comments but
doesn't exist yet, so right now any name goes
- the `dependencies` field in manifest_t is parsed into nothing,
it's aspirational at best
- no actual plugin conflict resolution beyond a boolean check
- no signature/checksum verification on downloaded repos, so
trust your sources
- gen-manifest just dumps a canned template, no interactive mode
Also, unrelated drive-by cleanup:
- CMakeLists: -pedantic -> -Wpedantic, one-line generate_version
target because vertical space is precious
- moved the giant default config/theme TOML strings out of
config.hpp into texts.hpp, config.hpp was starting to look
like a novel
- screenshot_tool.cpp: actually check the Result from
CopyText() instead of silently launching it into the void
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.
oshot started as a straightforward screenshot & annotation tool with a systray icon and an OCR pipeline bolted on for pulling text out of a selection. That already covers a lot of ground, but the moment you want oshot to do something it wasn't built for (a different OCR backend, a custom exporter, whatever), you're stuck forking the whole app just to scratch your own itch.
So here we are: plugins.
The idea is simple: give oshot a stable C ABI that anyone can link against, and let plugins hook into the parts of the app that actually matter - the init/render/destroy lifecycle, config and cache storage, logging, and (for OCR-adjacent plugins) the
on_ocr_doneresult callback.C ABI specifically, not C++: no name mangling, no vtable layout or STL ABI to keep in lockstep with whatever compiler/standard-library version oshot itself was built with, and no risk of a plugin silently breaking because it was built against a slightly different libstdc++/MSVC runtime. Practically, that also means plugins aren't locked into C++ at all, thus anything that can export a C-compatible interface (C/C++, Rust, Zig, even Python via ctypes/cffi) can load into oshot the same way, which is the whole point since the goal is to let people extend the app in whatever language they're comfortable with. Each plugin gets its own
config.toml, backed by the sameTomlAPIbase oshot already uses for its own Config/Cache, so nobody has to hand-roll a bespoke serialization format per plugin, unless they want to use a different configuration and similair, they are free to do so completely.cimgui(a C-ABI wrapper for ImGui) got pulled in specifically so plugin UI code isn't stuck writing raw ImGui calls from C++ across the ABI boundary.There's also a managing window now, so plugins can be toggled on/off without hand-editing a config file, and each plugin can register its own tab in the preferences window.
This is still WIP. The plugin API surface (
oshot_plugin.h) isn't frozen yet and will keep shifting until there's an actual manifest standard behind it. Right now "does this thing even have a unique id/name" is enforced at load time and not a whole lot else.TODO:
g_apisingleton misattribution bug)Un-related commits that should be in main