NeoMutt  2024-03-23-147-g885fbc
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
notify.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <stddef.h>
31#include <stdbool.h>
32#include "notify.h"
33#include "logging2.h"
34#include "memory.h"
35#include "notify_type.h"
36#include "observer.h"
37#include "queue.h"
38
41static const char *NotifyTypeNames[] = {
42 "NT_ALL", "NT_ACCOUNT", "NT_ALIAS", "NT_ALTERN", "NT_ATTACH",
43 "NT_BINDING", "NT_COLOR", "NT_COMMAND", "NT_CONFIG", "NT_CONTEXT",
44 "NT_EMAIL", "NT_ENVELOPE", "NT_GLOBAL", "NT_HEADER", "NT_INDEX",
45 "NT_MAILBOX", "NT_MENU", "NT_PAGER", "NT_RESIZE", "NT_SCORE",
46 "NT_SUBJRX", "NT_TIMEOUT", "NT_WINDOW",
47};
48
52struct Notify
53{
54 struct Notify *parent;
55 struct ObserverList observers;
56};
57
62struct Notify *notify_new(void)
63{
64 struct Notify *notify = mutt_mem_calloc(1, sizeof(*notify));
65
66 STAILQ_INIT(&notify->observers);
67
68 return notify;
69}
70
75void notify_free(struct Notify **ptr)
76{
77 if (!ptr || !*ptr)
78 return;
79
80 struct Notify *notify = *ptr;
81 // NOTIFY observers
82
84
85 FREE(ptr);
86}
87
95void notify_set_parent(struct Notify *notify, struct Notify *parent)
96{
97 if (!notify)
98 return;
99
100 notify->parent = parent;
101}
102
120static bool send(struct Notify *source, struct Notify *current,
121 enum NotifyType event_type, int event_subtype, void *event_data)
122{
123 if (!source || !current)
124 return false;
125
126 mutt_debug(LL_NOTIFY, "send: %d, %p\n", event_type, event_data);
127 struct ObserverNode *np = NULL;
128 STAILQ_FOREACH(np, &current->observers, entries)
129 {
130 struct Observer *o = np->observer;
131 if (!o)
132 continue;
133
134 if ((o->type == NT_ALL) || (event_type == o->type))
135 {
138 if (o->callback(&nc) < 0)
139 {
140 mutt_debug(LL_DEBUG1, "failed to send notification: %s/%d, global %p, event %p\n",
142 }
143 }
144 }
145
146 if (current->parent)
148
149 // Garbage collection time
150 struct ObserverNode *tmp = NULL;
151 STAILQ_FOREACH_SAFE(np, &current->observers, entries, tmp)
152 {
153 if (np->observer)
154 continue;
155
156 STAILQ_REMOVE(&current->observers, np, ObserverNode, entries);
157 FREE(&np);
158 }
159
160 return true;
161}
162
173bool notify_send(struct Notify *notify, enum NotifyType event_type,
174 int event_subtype, void *event_data)
175{
176 mutt_debug(LL_NOTIFY, "sending: %s/%d\n", NotifyTypeNames[event_type], event_subtype);
177 return send(notify, notify, event_type, event_subtype, event_data);
178}
179
191bool notify_observer_add(struct Notify *notify, enum NotifyType type,
192 observer_t callback, void *global_data)
193{
194 if (!notify || !callback)
195 return false;
196
197 struct ObserverNode *np = NULL;
198 STAILQ_FOREACH(np, &notify->observers, entries)
199 {
200 if (!np->observer)
201 continue; // LCOV_EXCL_LINE
202
203 if ((np->observer->callback == callback) && (np->observer->global_data == global_data))
204 return true;
205 }
206
207 struct Observer *o = mutt_mem_calloc(1, sizeof(*o));
208 o->type = type;
209 o->callback = callback;
211
212 np = mutt_mem_calloc(1, sizeof(*np));
213 np->observer = o;
214 STAILQ_INSERT_HEAD(&notify->observers, np, entries);
215
216 return true;
217}
218
231 const void *global_data)
232{
233 if (!notify || !callback)
234 return false;
235
236 struct ObserverNode *np = NULL;
237 STAILQ_FOREACH(np, &notify->observers, entries)
238 {
239 if (!np->observer)
240 continue; // LCOV_EXCL_LINE
241
242 if ((np->observer->callback == callback) && (np->observer->global_data == global_data))
243 {
244 FREE(&np->observer);
245 return true;
246 }
247 }
248
249 return false;
250}
251
257{
258 if (!notify)
259 return;
260
261 struct ObserverNode *np = NULL;
262 struct ObserverNode *tmp = NULL;
263 STAILQ_FOREACH_SAFE(np, &notify->observers, entries, tmp)
264 {
265 STAILQ_REMOVE(&notify->observers, np, ObserverNode, entries);
266 FREE(&np->observer);
267 FREE(&np);
268 }
269}
#define mutt_debug(LEVEL,...)
Definition: logging2.h:89
Logging Dispatcher.
@ LL_DEBUG1
Log at debug level 1.
Definition: logging2.h:43
@ LL_NOTIFY
Log of notifications.
Definition: logging2.h:48
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
Memory management wrappers.
#define FREE(x)
Definition: memory.h:45
bool notify_observer_remove(struct Notify *notify, const observer_t callback, const void *global_data)
Remove an observer from an object.
Definition: notify.c:230
static bool send(struct Notify *source, struct Notify *current, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:120
bool notify_observer_add(struct Notify *notify, enum NotifyType type, observer_t callback, void *global_data)
Add an observer to an object.
Definition: notify.c:191
struct Notify * notify_new(void)
Create a new notifications handler.
Definition: notify.c:62
static const char * NotifyTypeNames[]
Lookup table for NotifyType Must be the same size and order as NotifyType.
Definition: notify.c:41
void notify_observer_remove_all(struct Notify *notify)
Remove all the observers from an object.
Definition: notify.c:256
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:173
void notify_set_parent(struct Notify *notify, struct Notify *parent)
Set the parent notification handler.
Definition: notify.c:95
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:75
Notification API.
Notification Types.
NotifyType
Notification Types.
Definition: notify_type.h:34
@ NT_ALL
Register for all notifications.
Definition: notify_type.h:35
Observer of notifications.
int(* observer_t)(struct NotifyCallback *nc)
Definition: observer.h:54
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:402
#define STAILQ_INIT(head)
Definition: queue.h:372
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
#define STAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:383
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
Data passed to a notification function.
Definition: observer.h:34
void * event_data
Data from notify_send()
Definition: observer.h:38
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:36
struct Notify * current
Notify object being observed.
Definition: observer.h:35
int event_subtype
Send: Event subtype, e.g. NT_ACCOUNT_ADD.
Definition: observer.h:37
Notification API.
Definition: notify.c:53
struct Notify * parent
Parent of the notification object.
Definition: notify.c:54
struct ObserverList observers
List of observers of this object.
Definition: notify.c:55
List of Observers.
Definition: observer.h:70
struct Observer * observer
An Observer.
Definition: observer.h:71
An observer of notifications.
Definition: observer.h:60
observer_t callback
Callback function for events.
Definition: observer.h:62
void * global_data
Private data to pass to callback.
Definition: observer.h:63
enum NotifyType type
Notification type to observe, e.g. NT_WINDOW.
Definition: observer.h:61