diff --git a/src/inhibit-manager.c b/src/inhibit-manager.c new file mode 100644 index 0000000..64ffe07 --- /dev/null +++ b/src/inhibit-manager.c @@ -0,0 +1,236 @@ +#include "inhibit-interface.h" +#include +#include + +int inhibit_manager_init(InhibitManager* mgr) { + if (!mgr) + return -1; + memset(mgr, 0, sizeof(*mgr)); + return 0; +} + +void inhibit_manager_cleanup(InhibitManager* mgr) { + if (!mgr) + return; + + for (int i = 0; i < mgr->num_inhibits; i++) { + TrackedInhibit* tracked = &mgr->inhibits[i]; + InhibitInterface* iface = mgr->interfaces[tracked->interface_idx]; + if (iface && iface->uninhibit) { + iface->uninhibit(iface, &tracked->entry); + } + } + + for (int i = 0; i < mgr->num_interfaces; i++) { + if (mgr->interfaces[i] && mgr->interfaces[i]->cleanup) { + mgr->interfaces[i]->cleanup(mgr->interfaces[i]); + } + } + + memset(mgr, 0, sizeof(*mgr)); +} + +int inhibit_manager_register(InhibitManager* mgr, InhibitInterface* iface) { + if (!mgr || !iface || mgr->num_interfaces >= MAX_INTERFACES) { + return -1; + } + + iface->enabled = 1; + mgr->interfaces[mgr->num_interfaces] = iface; + iface->set_callback(iface, mgr->event_callback); + + if (iface->init(iface) < 0) { + fprintf(stderr, "Failed to initialize interface: %s\n", iface->name); + iface->enabled = 0; + return -1; + } + + mgr->num_interfaces++; + return 0; +} + +void inhibit_manager_set_callback(InhibitManager* mgr, InhibitEventCallback cb) { + if (!mgr) + return; + mgr->event_callback = cb; + for (int i = 0; i < mgr->num_interfaces; i++) { + if (mgr->interfaces[i] && mgr->interfaces[i]->set_callback) { + mgr->interfaces[i]->set_callback(mgr->interfaces[i], cb); + } + } +} + +TrackedInhibit* inhibit_manager_find(InhibitManager* mgr, InhibitInterface* source, + const char* id) { + if (!mgr || !id) + return NULL; + + for (int i = 0; i < mgr->num_inhibits; i++) { + TrackedInhibit* tracked = &mgr->inhibits[i]; + if (strcmp(tracked->entry.id, id) == 0) { + if (!source || mgr->interfaces[tracked->interface_idx] == source) { + return tracked; + } + } + } + return NULL; +} + +int inhibit_manager_add_tracked(InhibitManager* mgr, InhibitInterface* source, + const InhibitEntry* entry) { + if (!mgr || !source || !entry || + mgr->num_inhibits >= (MAX_INTERFACES * MAX_INHIBITS_PER_INTERFACE)) { + return -1; + } + + int source_idx = -1; + for (int i = 0; i < mgr->num_interfaces; i++) { + if (mgr->interfaces[i] == source) { + source_idx = i; + break; + } + } + + if (source_idx < 0) + return -1; + + TrackedInhibit* tracked = &mgr->inhibits[mgr->num_inhibits]; + memcpy(&tracked->entry, entry, sizeof(*entry)); + tracked->interface_idx = source_idx; + tracked->num_forwarded = 0; + + mgr->num_inhibits++; + return 0; +} + +void inhibit_manager_remove_tracked(InhibitManager* mgr, InhibitInterface* source, const char* id) { + if (!mgr || !id) + return; + + for (int i = 0; i < mgr->num_inhibits; i++) { + TrackedInhibit* tracked = &mgr->inhibits[i]; + if (strcmp(tracked->entry.id, id) == 0) { + if (!source || mgr->interfaces[tracked->interface_idx] == source) { + for (int j = i; j < mgr->num_inhibits - 1; j++) { + mgr->inhibits[j] = mgr->inhibits[j + 1]; + } + mgr->num_inhibits--; + return; + } + } + } +} + +int inhibit_manager_forward_inhibit(InhibitManager* mgr, InhibitInterface* source, + const InhibitEntry* entry) { + if (!mgr || !source || !entry) + return -1; + + if (entry->flags & INHIBIT_FLAG_FORWARDED) { + return 0; + } + + TrackedInhibit* tracked = inhibit_manager_find(mgr, source, entry->id); + if (!tracked) { + inhibit_manager_add_tracked(mgr, source, entry); + tracked = inhibit_manager_find(mgr, source, entry->id); + } + + if (!tracked) + return -1; + + for (int i = 0; i < mgr->num_interfaces; i++) { + InhibitInterface* target = mgr->interfaces[i]; + if (target == source || !target->enabled || !target->inhibit) { + continue; + } + + int already_forwarded = 0; + for (int j = 0; j < tracked->num_forwarded; j++) { + if (strcmp(tracked->forwarded_to[j], target->name) == 0) { + already_forwarded = 1; + break; + } + } + + if (already_forwarded) + continue; + + InhibitEntry forwarded_entry = *entry; + forwarded_entry.flags |= INHIBIT_FLAG_FORWARDED; + memset(forwarded_entry.id, 0, sizeof(forwarded_entry.id)); + + if (target->inhibit(target, entry->type, entry->app_name, entry->reason, &forwarded_entry) == + 0) { + if (tracked->num_forwarded < MAX_INTERFACES) { + strncpy(tracked->forwarded_to[tracked->num_forwarded], target->name, INHIBIT_ID_LEN - 1); + tracked->num_forwarded++; + } else { + fprintf(stderr, "Warning: inhibit forwarded to %s but tracking limit reached\n", + target->name); + } + } + } + + return 0; +} + +int inhibit_manager_forward_uninhibit(InhibitManager* mgr, InhibitInterface* source, + const InhibitEntry* entry) { + if (!mgr || !source || !entry) + return -1; + + TrackedInhibit* tracked = inhibit_manager_find(mgr, source, entry->id); + if (!tracked) + return -1; + + for (int i = 0; i < tracked->num_forwarded; i++) { + for (int j = 0; j < mgr->num_interfaces; j++) { + InhibitInterface* target = mgr->interfaces[j]; + if (strcmp(target->name, tracked->forwarded_to[i]) == 0 && target->uninhibit) { + target->uninhibit(target, &tracked->entry); + break; + } + } + } + + inhibit_manager_remove_tracked(mgr, source, entry->id); + return 0; +} + +void inhibit_manager_poll_all(InhibitManager* mgr) { + if (!mgr) + return; + + for (int i = 0; i < mgr->num_interfaces; i++) { + InhibitInterface* iface = mgr->interfaces[i]; + if (iface->enabled && iface->poll) { + iface->poll(iface); + } + } +} + +const char* inhibit_type_to_string(InhibitType type) { + switch (type) { + case INHIBIT_TYPE_SCREENSAVER: + return "screensaver"; + case INHIBIT_TYPE_SUSPEND: + return "suspend"; + case INHIBIT_TYPE_IDLE: + return "idle"; + default: + return "unknown"; + } +} + +InhibitType inhibit_type_from_string(const char* str) { + if (!str) + return INHIBIT_TYPE_IDLE; + if (strcmp(str, "screensaver") == 0) + return INHIBIT_TYPE_SCREENSAVER; + if (strcmp(str, "suspend") == 0) + return INHIBIT_TYPE_SUSPEND; + if (strcmp(str, "idle") == 0) + return INHIBIT_TYPE_IDLE; + return INHIBIT_TYPE_IDLE; +}