public abstract class DBusServiceBase : Object { protected uint dbus_watch_id; public bool is_connected { get; private set; default = false; } protected const string DBUS_PATH = "/net/buzzert/kordophonecd/daemon"; protected const string DBUS_NAME = "net.buzzert.kordophonecd"; protected DBusServiceBase() { connect_to_dbus.begin((obj, res) => { connect_to_dbus.end(res); }); } ~DBusServiceBase() { if (dbus_watch_id > 0) { Bus.unwatch_name(dbus_watch_id); } } protected abstract void setup_signals(); protected abstract async Object? get_proxy() throws Error; protected abstract string get_service_name(); private async void connect_to_dbus() { try { debug("Trying to connect to %s service at path: %s", get_service_name(), DBUS_PATH); var proxy = yield get_proxy(); if (proxy == null) { throw new Error(1337, 1, "Failed to get proxy"); } // If we get here, connection succeeded debug("Connected to %s service at path: %s", get_service_name(), DBUS_PATH); is_connected = true; setup_signals(); } catch (Error e) { debug("Failed to connect to %s at %s: %s", get_service_name(), DBUS_PATH, e.message); } if (!is_connected) { warning("Failed to connect to %s on any known path", get_service_name()); // Watch for the service to appear dbus_watch_id = Bus.watch_name(BusType.SESSION, DBUS_NAME, BusNameWatcherFlags.AUTO_START, () => { connect_to_dbus.begin(); }, null); } } protected Error create_not_connected_error() { return new Error(1337, 1, @"$(get_service_name()) not connected"); } }