Commit graph

6 commits

Author SHA1 Message Date
57fe7ff53a fix(service): wait for launchd to drop the old job before loading the new
- Update now stopped the daemon and failed with "Bootstrap failed: 5: Input/output error" on macOS, leaving the agent's plist written and no job loaded. `launchctl bootout` returns once the daemon has been sent SIGTERM, and launchd refuses `bootstrap` until the daemon has exited and the job has left the domain.
- Installing or replacing the launchd agent now waits for the booted-out job to leave, for up to 25 seconds, which covers the 20 seconds launchd allows before SIGKILL.
- Starting the service now loads the agent's plist first when launchd does not hold the job, so the window's Start button and `service start` recover a registration left unloaded instead of failing in `kickstart`.
- The stand-in launchctl in the service lifecycle test returns from `bootout` while the daemon is still stopping and refuses `bootstrap` until it has gone, as launchd does, so `service install --start` over a running daemon pins the regression.
2026-10-04 08:43:28 -05:00
43f7b8916b fix(appimage): install the desktop entry so the window gets its icon
- A Wayland desktop finds a window's icon by looking up its application ID among the installed desktop entries. An AppImage carries its entry and icon inside its own tree, where no desktop looks, so its window showed the generic Wayland icon and Midi Harbor was missing from the application menu.
- Run from an AppImage, the window now installs com.mrgeckosmedia.MidiHarbor.desktop under $XDG_DATA_HOME/applications and the icon under icons/hicolor/scalable/apps before it opens. Exec is rewritten to the AppImage file, quoted as the Desktop Entry Specification requires, and each file is written only when it differs, so a moved AppImage is followed.
- TryExec names the AppImage file, so desktops stop offering the entry once the file is deleted, which is how an AppImage is removed.
- Nothing is installed when a directory in XDG_DATA_DIRS already holds the entry: one under the user's directory takes precedence and would point a package's menu item at the AppImage.
2026-10-02 12:32:08 -05:00
5dce49ee43 feat(update): say when the daemon is another build and update it on request
- A daemon keeps running the copy it was started from, so after an update the old one ran until the next login and nothing said so; clients compared only the major protocol version. Every build now carries a UUID, the daemon reports it as ServerInfo.build_id under protocol 1.3, and a daemon too old to report one counts as outdated.
- The window shows a notice above every page when the daemon it reached is another build, with both versions. Update now registers the copy that was opened as the service and restarts the daemon from it; Not now puts the notice away. Nothing is restarted unless the user asks, so two copies open at once cannot replace each other's daemon in turn. A newer daemon is offered as Use this version, and one the service did not start, or one reached with --socket, gets no button.
- service install --start now stops a running daemon before registering and starting, so the daemon started is the program that was asked. Under systemd and Task Scheduler it used to rewrite the registration and leave the old daemon running, since starting a running service does nothing.
- service status says when the daemon is another build than the program asked, and --json carries same_build.
- The App Store app stops a daemon another build of the app left running and starts its own, instead of attaching to it.
- Packaging sets MIDI_HARBOR_BUILD_ID once for everything a run builds, because the App Store app, its helper and each architecture are compiled separately and must agree. Packages of one release share an identifier, so neither replaces the other's daemon.
2026-10-02 11:56:27 -05:00
d11a525008 feat(release): publish an AppImage for each Linux architecture
- Releases now include Midi-Harbor-<version>-<x86_64|aarch64>.AppImage, built from the same binary as the packages and listed in checksums.txt, for distributions without a .deb or .rpm. Opened with no arguments it shows the window, and the daemon it registers runs under the systemd user unit like a package install.
- service install run from an AppImage registers the .AppImage file instead of the executable inside the runtime's temporary mount, which is gone once the process exits. The file is used only when the running executable is inside APPDIR, so a program started from another AppImage, whose APPIMAGE it inherits, still registers itself.
- The AppImage carries only the Avahi client libraries from the Debian 12 sysroot, with their LGPL-2.1 license, found through the binary's RUNPATH rather than LD_LIBRARY_PATH; glibc 2.35 or newer, ALSA, D-Bus and libxkbcommon come from the host, as for the packages.
- Its AppRun starts the binary as midi-harbor, so on X11 the window's class matches the desktop entry instead of the AppImage's file name.
- Building it needs the cross image's new patchelf, file, appimagetool 1.9.1 and type2 runtime 20251108, pinned by checksum, and a sysroot rebuilt to carry Avahi's license; the script stops and names make build-sysroot when that license is missing.
2026-09-29 14:35:51 -05:00
92cc30e381 fix(service): stop the daemon before the rest of its systemd unit
- The systemd user unit now has an ExecStop that sends SIGTERM to the main process and waits for it to exit; only then does systemd signal whatever else remains in the unit.
- By default systemd signalled every process in the unit at once. Run from an AppImage, that included the runtime serving the daemon's executable, which unmounted while the daemon was still shutting down: every stop and logout ended in SIGBUS and a core dump before held notes were released.
- A daemon installed from a package is alone in its unit and stops as before. Existing registrations gain the ExecStop when service install is run again.
2026-09-29 14:35:38 -05:00
488e42b9c8 First commit 2026-09-28 13:59:10 -05:00