NeoMutt  2021-02-05-666-ge300cd
Teaching an old dog new tricks
DOXYGEN
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 "logging.h"
34 #include "memory.h"
35 #include "queue.h"
36 
39 static char *NotifyTypeNames[] = {
40  "NT_ALL", "NT_ACCOUNT", "NT_ALIAS", "NT_ALTERN", "NT_ATTACH",
41  "NT_BINDING", "NT_COLOR", "NT_COMMAND", "NT_COMPOSE", "NT_CONFIG",
42  "NT_CONTEXT", "NT_EMAIL", "NT_GLOBAL", "NT_HEADER", "NT_INDEX",
43  "NT_MAILBOX", "NT_MENU", "NT_PAGER", "NT_SCORE", "NT_SUBJRX",
44  "NT_WINDOW",
45 };
46 
50 struct Notify
51 {
52  struct Notify *parent;
53  struct ObserverList observers;
54 };
55 
60 struct Notify *notify_new(void)
61 {
62  struct Notify *notify = mutt_mem_calloc(1, sizeof(*notify));
63 
64  STAILQ_INIT(&notify->observers);
65 
66  return notify;
67 }
68 
73 void notify_free(struct Notify **ptr)
74 {
75  if (!ptr || !*ptr)
76  return;
77 
78  struct Notify *notify = *ptr;
79  // NOTIFY observers
80 
82 
83  FREE(ptr);
84 }
85 
94 {
95  if (!notify)
96  return;
97 
98  notify->parent = parent;
99 }
100 
118 static bool send(struct Notify *source, struct Notify *current,
119  enum NotifyType event_type, int event_subtype, void *event_data)
120 {
121  if (!source || !current)
122  return false;
123 
124  mutt_debug(LL_NOTIFY, "send: %d, %ld\n", event_type, event_data);
125  struct ObserverNode *np = NULL;
126  STAILQ_FOREACH(np, &current->observers, entries)
127  {
128  struct Observer *o = np->observer;
129  if (!o)
130  continue;
131 
132  if ((o->type == NT_ALL) || (event_type == o->type))
133  {
135  event_data, o->global_data };
136  if (o->callback(&nc) < 0)
137  {
138  mutt_debug(LL_DEBUG1, "failed to send notification: %s/%d, global %p, event %p\n",
139  NotifyTypeNames[event_type], event_subtype, o->global_data, event_data);
140  }
141  }
142  }
143 
144  if (current->parent)
145  return send(source, current->parent, event_type, event_subtype, event_data);
146 
147  // Garbage collection time
148  struct ObserverNode *tmp = NULL;
149  STAILQ_FOREACH_SAFE(np, &current->observers, entries, tmp)
150  {
151  if (np->observer)
152  continue;
153 
154  STAILQ_REMOVE(&current->observers, np, ObserverNode, entries);
155  FREE(&np);
156  }
157 
158  return true;
159 }
160 
171 bool notify_send(struct Notify *notify, enum NotifyType event_type,
172  int event_subtype, void *event_data)
173 {
174  mutt_debug(LL_NOTIFY, "sending: %s/%d\n", NotifyTypeNames[event_type], event_subtype);
175  return send(notify, notify, event_type, event_subtype, event_data);
176 }
177 
189 bool notify_observer_add(struct Notify *notify, enum NotifyType type,
190  observer_t callback, void *global_data)
191 {
192  if (!notify || !callback)
193  return false;
194 
195  struct ObserverNode *np = NULL;
196  STAILQ_FOREACH(np, &notify->observers, entries)
197  {
198  if (!np->observer)
199  continue;
200 
201  if ((np->observer->callback == callback) && (np->observer->global_data == global_data))
202  return true;
203  }
204 
205  struct Observer *o = mutt_mem_calloc(1, sizeof(*o));
206  o->type = type;
207  o->callback = callback;
209 
210  np = mutt_mem_calloc(1, sizeof(*np));
211  np->observer = o;
212  STAILQ_INSERT_HEAD(&notify->observers, np, entries);
213 
214  return true;
215 }
216 
229 {
230  if (!notify || !callback)
231  return false;
232 
233  struct ObserverNode *np = NULL;
234  STAILQ_FOREACH(np, &notify->observers, entries)
235  {
236  if (!np->observer)
237  continue;
238 
239  if ((np->observer->callback == callback) && (np->observer->global_data == global_data))
240  {
241  FREE(&np->observer);
242  return true;
243  }
244  }
245 
246  return false;
247 }
248 
254 {
255  if (!notify)
256  return;
257 
258  struct ObserverNode *np = NULL;
259  struct ObserverNode *tmp = NULL;
260  STAILQ_FOREACH_SAFE(np, &notify->observers, entries, tmp)
261  {
262  STAILQ_REMOVE(&notify->observers, np, ObserverNode, entries);
263  FREE(&np->observer);
264  FREE(&np);
265  }
266 }
Notification API.
static char * NotifyTypeNames[]
Lookup table for NotifyType Must be the same size and order as NotifyType.
Definition: notify.c:39
void * mutt_mem_calloc(size_t nmemb, size_t size)
Allocate zeroed memory on the heap.
Definition: memory.c:50
#define STAILQ_REMOVE(head, elm, type, field)
Definition: queue.h:402
Memory management wrappers.
Data passed to a notification function.
Definition: observer.h:39
Log of notifications.
Definition: logging.h:45
void notify_free(struct Notify **ptr)
Free a notification handler.
Definition: notify.c:73
struct Observer * observer
An Observer.
Definition: observer.h:75
struct Notify * notify
Notifications: ColorId, EventColor.
Definition: color.c:95
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:118
void * global_data
Private data to pass to callback.
Definition: observer.h:67
Logging Dispatcher.
NotifyType
Notification Types.
Definition: notify_type.h:31
int event_subtype
Send: Event subtype, e.g. NT_ACCOUNT_ADD.
Definition: observer.h:43
enum NotifyType event_type
Send: Event type, e.g. NT_ACCOUNT.
Definition: observer.h:42
int(* observer_t)(struct NotifyCallback *nc)
Prototype for a notification callback function.
Definition: observer.h:58
#define STAILQ_INIT(head)
Definition: queue.h:372
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:189
enum NotifyType type
Notification type to observe, e.g. NT_WINDOW.
Definition: observer.h:65
#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
Definition: queue.h:362
struct Notify * notify_new(void)
Create a new notifications handler.
Definition: notify.c:60
struct Notify * parent
Definition: notify.c:52
struct ObserverList observers
Definition: notify.c:53
#define STAILQ_INSERT_HEAD(head, elm, field)
Definition: queue.h:383
An observer of notifications.
Definition: observer.h:63
Notification API.
Definition: notify.c:50
struct Notify * current
Notify object being observed.
Definition: observer.h:41
#define STAILQ_FOREACH(var, head, field)
Definition: queue.h:352
static void * global_data
Original opaque data in fallback implementation.
Definition: qsort_r.c:41
#define mutt_debug(LEVEL,...)
Definition: logging.h:85
List of Observers.
Definition: observer.h:73
void * event_data
Data from notify_send()
Definition: observer.h:44
void notify_observer_remove_all(struct Notify *notify)
Remove all the observers from an object.
Definition: notify.c:253
Log at debug level 1.
Definition: logging.h:40
Register for all notifications.
Definition: notify_type.h:33
#define FREE(x)
Definition: memory.h:40
bool notify_observer_remove(struct Notify *notify, observer_t callback, void *global_data)
Remove an observer from an object.
Definition: notify.c:228
observer_t callback
Callback function for events.
Definition: observer.h:66
void notify_set_parent(struct Notify *notify, struct Notify *parent)
Set the parent notification handler.
Definition: notify.c:93
bool notify_send(struct Notify *notify, enum NotifyType event_type, int event_subtype, void *event_data)
Send out a notification message.
Definition: notify.c:171