add growl agent for macos
[openafs.git] / src / platform / DARWIN / growlagent / GrowlDefinesInternal.h
1 //
2 //  GrowlDefinesInternal.h
3 //  Growl
4 //
5 //  Created by Karl Adam on Mon May 17 2004.
6 //  Copyright (c) 2004 the Growl Project. All rights reserved.
7 //
8
9 #ifndef _GROWL_GROWLDEFINESINTERNAL_H
10 #define _GROWL_GROWLDEFINESINTERNAL_H
11
12 #include <CoreFoundation/CoreFoundation.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15
16 #ifdef __OBJC__
17 #define XSTR(x) (@x)
18 #else /* !__OBJC__ */
19 #define XSTR CFSTR
20 #endif /* __OBJC__ */
21
22 /*!     @header GrowlDefinesInternal.h
23  *      @abstract       Defines internal Growl macros and types.
24  *  @ignore ATTRIBUTE_PACKED
25  *      @discussion     These constants are used both by GrowlHelperApp and by plug-ins.
26  *
27  *       Notification keys (used in GrowlHelperApp, in GrowlApplicationBridge, and
28  *       by applications that don't use GrowlApplicationBridge) are defined in
29  *       GrowlDefines.h.
30  */
31
32 /*!
33  * @defined NSInteger
34  * @abstract Typedef to int so Growl will compile on pre-10.5 SDKs.
35  */
36 #ifndef NSINTEGER_DEFINED
37 typedef int NSInteger;
38 typedef unsigned int NSUInteger;
39 #define NSINTEGER_DEFINED
40 #endif
41
42 /*!
43  * @defined CGFloat
44  * @abstract Typedef to float so Growl will compile on pre-10.5 SDKs.
45  */
46 #ifndef CGFLOAT_DEFINED
47 typedef float CGFloat;
48 #define CGFLOAT_IS_DOUBLE 0
49 #define CGFLOAT_DEFINED
50 #endif
51
52 /*!
53  * @defined GrowlCGFloatCeiling()
54  * @abstract Macro for the ceil() function that uses a different precision depending on the CPU architecture.
55  */
56 /*!
57  * @defined GrowlCGFloatAbsoluteValue()
58  * @abstract Macro for the fabs() function that uses a different precision depending on the CPU architecture.
59  */
60 /*!
61  * @defined GrowlCGFloatFloor()
62  * @abstract Macro for the floor() function that uses a different precision depending on the CPU architecture.
63  */
64 #if CGFLOAT_IS_DOUBLE
65 #define GrowlCGFloatCeiling(x) ceil(x)
66 #define GrowlCGFloatAbsoluteValue(x) fabs(x)
67 #define GrowlCGFloatFloor(x) floor(x)
68 #else
69 #define GrowlCGFloatCeiling(x) ceilf(x)
70 #define GrowlCGFloatAbsoluteValue(x) fabsf(x)
71 #define GrowlCGFloatFloor(x) floorf(x)
72 #endif
73
74 /*!     @defined        GROWL_TCP_PORT
75  *      @abstract       The TCP listen port for Growl notification servers.
76  */
77 #define GROWL_TCP_PORT  23052
78
79 /*!     @defined        GROWL_UDP_PORT
80  *      @abstract       The UDP listen port for Growl notification servers.
81  */
82 #define GROWL_UDP_PORT  9887
83
84 /*!     @defined        GROWL_PROTOCOL_VERSION
85  *      @abstract       The current version of the Growl network-notifications protocol (without encryption).
86  */
87 #define GROWL_PROTOCOL_VERSION  1
88
89 /*!     @defined        GROWL_PROTOCOL_VERSION_AES128
90 *       @abstract       The current version of the Growl network-notifications protocol (with AES-128 encryption).
91 */
92 #define GROWL_PROTOCOL_VERSION_AES128   2
93
94 /*!     @defined        GROWL_TYPE_REGISTRATION
95  *      @abstract       The packet type of registration packets with MD5 authentication.
96  */
97 #define GROWL_TYPE_REGISTRATION                 0
98 /*!     @defined        GROWL_TYPE_NOTIFICATION
99  *      @abstract       The packet type of notification packets with MD5 authentication.
100  */
101 #define GROWL_TYPE_NOTIFICATION                 1
102 /*!     @defined        GROWL_TYPE_REGISTRATION_SHA256
103  *      @abstract       The packet type of registration packets with SHA-256 authentication.
104  */
105 #define GROWL_TYPE_REGISTRATION_SHA256  2
106 /*!     @defined        GROWL_TYPE_NOTIFICATION_SHA256
107  *      @abstract       The packet type of notification packets with SHA-256 authentication.
108  */
109 #define GROWL_TYPE_NOTIFICATION_SHA256  3
110 /*!     @defined        GROWL_TYPE_REGISTRATION_NOAUTH
111 *       @abstract       The packet type of registration packets without authentication.
112 */
113 #define GROWL_TYPE_REGISTRATION_NOAUTH  4
114 /*!     @defined        GROWL_TYPE_NOTIFICATION_NOAUTH
115 *       @abstract       The packet type of notification packets without authentication.
116 */
117 #define GROWL_TYPE_NOTIFICATION_NOAUTH  5
118
119 #define ATTRIBUTE_PACKED __attribute((packed))
120
121 /*!     @struct GrowlNetworkPacket
122  *      @abstract       This struct is a header common to all incoming Growl network
123  *       packets which identifies the type and version of the packet.
124  */
125 struct GrowlNetworkPacket {
126         unsigned char version;
127         unsigned char type;
128 } ATTRIBUTE_PACKED;
129
130 /*!
131  * @struct GrowlNetworkRegistration
132  * @abstract The format of a registration packet.
133  * @discussion A Growl client that wants to register with a Growl server sends
134  * a packet in this format.
135  * @field common The Growl packet header.
136  * @field appNameLen The name of the application that is registering.
137  * @field numAllNotifications The number of notifications in the list.
138  * @field numDefaultNotifications The number of notifications in the list that are enabled by default.
139  * @field data Variable-sized data.
140  */
141 struct GrowlNetworkRegistration {
142         struct GrowlNetworkPacket common;
143         /*      This name is used both internally and in the Growl
144          *       preferences.
145          *
146          *       The application name should remain stable between different versions
147          *       and incarnations of your application.
148          *       For example, "SurfWriter" is a good app name, whereas "SurfWriter 2.0"
149          *       and "SurfWriter Lite" are not.
150          *
151          *       In addition to being unsigned, the application name length is in
152          *       network byte order.
153          */
154         unsigned short appNameLen;
155         /*      These names are used both internally and in the Growl
156          *       preferences. For this reason, they should be human-readable.
157          */
158         unsigned char numAllNotifications;
159
160         unsigned char numDefaultNotifications;
161         /*      The variable-sized data of a registration is:
162          *       - The application name, in UTF-8 encoding, for appNameLen bytes.
163          *       - The list of all notification names.
164          *       - The list of default notifications, as 8-bit unsigned indices into the list of all notifications.
165          *       - The MD5/SHA256 checksum of all the data preceding the checksum.
166          *
167          *       Each notification name is encoded as:
168          *       - Length: two bytes, unsigned, network byte order.
169          *       - Name: As many bytes of UTF-8-encoded text as the length says.
170          *       And there are numAllNotifications of these.
171          */
172         unsigned char data[];
173 } ATTRIBUTE_PACKED;
174
175 /*!
176  * @struct GrowlNetworkNotification
177  * @abstract The format of a notification packet.
178  * @discussion  A Growl client that wants to post a notification to a Growl
179  * server sends a packet in this format.
180  * @field common The Growl packet header.
181  * @field flags The priority number and the sticky bit.
182  * @field nameLen The length of the notification name.
183  * @field titleLen The length of the notification title.
184  * @field descriptionLen The length of the notification description.
185  * @field appNameLen The length of the application name.
186  * @field data Variable-sized data.
187  */
188 struct GrowlNetworkNotification {
189         struct GrowlNetworkPacket common;
190         /*!
191          * @struct GrowlNetworkNotificationFlags
192          * @abstract Various flags.
193          * @discussion This 16-bit packed structure contains the priority as a
194          *  signed 3-bit integer from -2 to +2, and the sticky flag as a single bit.
195          *  The high 12 bits of the structure are reserved for future use.
196          * @field reserved reserved for future use.
197          * @field priority the priority as a signed 3-bit integer from -2 to +2.
198          * @field sticky the sticky flag.
199          */
200         struct GrowlNetworkNotificationFlags {
201 #ifdef __BIG_ENDIAN__
202                 unsigned reserved: 12;
203                 signed   priority: 3;
204                 unsigned sticky:   1;
205 #else
206                 unsigned sticky:   1;
207                 signed   priority: 3;
208                 unsigned reserved: 12;
209 #endif
210         } ATTRIBUTE_PACKED flags; //size = 16 (12 + 3 + 1)
211
212         /*      In addition to being unsigned, the notification name length
213          *       is in network byte order.
214          */
215         unsigned short nameLen;
216         /*      @discussion     In addition to being unsigned, the title length is in
217          *       network byte order.
218          */
219         unsigned short titleLen;
220         /*      In addition to being unsigned, the description length is in
221          *       network byte order.
222          */
223         unsigned short descriptionLen;
224         /*      In addition to being unsigned, the application name length
225          *       is in network byte order.
226          */
227         unsigned short appNameLen;
228         /*      The variable-sized data of a notification is:
229          *       - Notification name, in UTF-8 encoding, for nameLen bytes.
230          *       - Title, in UTF-8 encoding, for titleLen bytes.
231          *       - Description, in UTF-8 encoding, for descriptionLen bytes.
232          *       - Application name, in UTF-8 encoding, for appNameLen bytes.
233          *       - The MD5/SHA256 checksum of all the data preceding the checksum.
234          */
235         unsigned char data[];
236 } ATTRIBUTE_PACKED;
237
238 /*!     @defined        GrowlEnabledKey
239  *      @abstract       Preference key controlling whether Growl is enabled.
240  *      @discussion     If this is false, then when GrowlHelperApp is launched to open
241  *       a Growl registration dictionary file, GrowlHelperApp will quit when it has
242  *       finished processing the file instead of listening for notifications.
243  */
244 #define GrowlEnabledKey                                 XSTR("GrowlEnabled")
245
246 /*!     @defined        GROWL_SCREENSHOT_MODE
247  *      @abstract       Preference and notification key controlling whether to save a screenshot of the notification.
248  *      @discussion     This is for GHA's private usage. If your application puts this
249  *       key into a notification dictionary, GHA will clobber it. This key is only
250  *       allowed in the notification dictionaries GHA passes to displays.
251  *
252  *       If this key contains an object whose boolValue is not NO, the display is
253  *       asked to save a screenshot of the notification to
254  *       ~/Library/Application\ Support/Growl/Screenshots.
255  */
256 #define GROWL_SCREENSHOT_MODE                   XSTR("ScreenshotMode")
257
258 /*!     @defined        GROWL_APP_LOCATION
259  *      @abstract       The location of this application.
260  *      @discussion     Contains either the POSIX path to the application, or a file-data dictionary (as used by the Dock).
261  *       contains the file's alias record and its pathname.
262  */
263 #define GROWL_APP_LOCATION                              XSTR("AppLocation")
264
265 /*!     @defined        GROWL_REMOTE_ADDRESS
266  *      @abstract       The address of the host who sent this notification/registration.
267  *      @discussion     Contains an NSData with the address of the remote host who
268  *    sent this notification/registration.
269  */
270 #define GROWL_REMOTE_ADDRESS                    XSTR("RemoteAddress")
271
272 /*!
273  *      @defined    GROWL_PREFPANE_BUNDLE_IDENTIFIER
274  *      @discussion The bundle identifier for the Growl preference pane.
275  */
276 #define GROWL_PREFPANE_BUNDLE_IDENTIFIER                XSTR("com.growl.prefpanel")
277 /*!
278  *      @defined    GROWL_HELPERAPP_BUNDLE_IDENTIFIER
279  *      @discussion The bundle identifier for the Growl background application (GrowlHelperApp).
280  */
281 #define GROWL_HELPERAPP_BUNDLE_IDENTIFIER       XSTR("com.Growl.GrowlHelperApp")
282
283 /*!
284  *      @defined    GROWL_PREFPANE_NAME
285  *      @discussion The file name of the Growl preference pane.
286  */
287 #define GROWL_PREFPANE_NAME                                             XSTR("Growl.prefPane")
288 #define PREFERENCE_PANES_SUBFOLDER_OF_LIBRARY   XSTR("PreferencePanes")
289 #define PREFERENCE_PANE_EXTENSION                               XSTR("prefPane")
290
291 //plug-in bundle filename extensions
292 #define GROWL_PLUGIN_EXTENSION                  XSTR("growlPlugin")
293 #define GROWL_PATHWAY_EXTENSION                 XSTR("growlPathway")
294 #define GROWL_VIEW_EXTENSION                                    XSTR("growlView")
295 #define GROWL_STYLE_EXTENSION                                   XSTR("growlStyle")
296
297 /* --- These following macros are intended for plug-ins --- */
298
299 /*!     @function    SYNCHRONIZE_GROWL_PREFS
300  *      @abstract    Synchronizes Growl prefs so they're up-to-date.
301  *      @discussion  This macro is intended for use by GrowlHelperApp and by
302  *       plug-ins (when the prefpane is selected).
303  */
304 #define SYNCHRONIZE_GROWL_PREFS() CFPreferencesAppSynchronize(CFSTR("com.Growl.GrowlHelperApp"))
305
306 /*!     @function    UPDATE_GROWL_PREFS
307  *      @abstract    Tells GrowlHelperApp to update its prefs.
308  *      @discussion  This macro is intended for use by plug-ins.
309  *       It sends a notification to tell GrowlHelperApp to update its preferences.
310  */
311 #define UPDATE_GROWL_PREFS() do { \
312         SYNCHRONIZE_GROWL_PREFS(); \
313         CFStringRef _key = CFSTR("pid"); \
314         int pid = getpid(); \
315         CFNumberRef _value = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &pid); \
316         CFDictionaryRef userInfo = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&_key, (const void **)&_value, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); \
317         CFRelease(_value); \
318         CFNotificationCenterPostNotification(CFNotificationCenterGetDistributedCenter(), \
319                                                                                  CFSTR("GrowlPreferencesChanged"), \
320                                                                                  CFSTR("GrowlUserDefaults"), \
321                                                                                  userInfo, false); \
322         CFRelease(userInfo); \
323         } while(0)
324
325 /*!     @function    READ_GROWL_PREF_VALUE
326  *      @abstract    Reads the given pref value from the plug-in's preferences.
327  *      @discussion  This macro is intended for use by plug-ins. It reads the value for the
328  *       given key from the plug-in's preferences (which are stored in a dictionary inside of
329  *       GrowlHelperApp's prefs).
330  *      @param  key     The preference key to read the value of.
331  *      @param  domain  The bundle ID of the plug-in.
332  *      @param  type    The type of the result expected.
333  *      @param  result  A pointer to an id. Set to the value if exists, left unchanged if not.
334  *
335  *       If the value is set, you are responsible for releasing it.
336  */
337 #define READ_GROWL_PREF_VALUE(key, domain, type, result) do {\
338         CFDictionaryRef prefs = (CFDictionaryRef)CFPreferencesCopyAppValue((CFStringRef)domain, \
339                                                                                                                                                 CFSTR("com.Growl.GrowlHelperApp")); \
340         if (prefs) {\
341                 if (CFDictionaryContainsKey(prefs, key)) {\
342                         *result = (type)CFDictionaryGetValue(prefs, key); \
343                         CFRetain(*result); \
344                 } \
345                 CFRelease(prefs); } \
346         } while(0)
347
348 /*!     @function    WRITE_GROWL_PREF_VALUE
349  *      @abstract    Writes the given pref value to the plug-in's preferences.
350  *      @discussion  This macro is intended for use by plug-ins. It writes the given
351  *       value to the plug-in's preferences.
352  *      @param  key     The preference key to write the value of.
353  *      @param  value   The value to write to the preferences. It should be either a
354  *       CoreFoundation type or toll-free bridged with one.
355  *      @param  domain  The bundle ID of the plug-in.
356  */
357 #define WRITE_GROWL_PREF_VALUE(key, value, domain) do {\
358         CFDictionaryRef staticPrefs = (CFDictionaryRef)CFPreferencesCopyAppValue((CFStringRef)domain, \
359                                                                                                                                                          CFSTR("com.Growl.GrowlHelperApp")); \
360         CFMutableDictionaryRef prefs; \
361         if (staticPrefs == NULL) {\
362                 prefs = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); \
363         } else {\
364                 prefs = CFDictionaryCreateMutableCopy(NULL, 0, staticPrefs); \
365                 CFRelease(staticPrefs); \
366         }\
367         CFDictionarySetValue(prefs, key, value); \
368         CFPreferencesSetAppValue((CFStringRef)domain, prefs, CFSTR("com.Growl.GrowlHelperApp")); \
369         CFRelease(prefs); } while(0)
370
371 /*!     @function    READ_GROWL_PREF_BOOL
372  *      @abstract    Reads the given Boolean from the plug-in's preferences.
373  *      @discussion  This is a wrapper around READ_GROWL_PREF_VALUE() intended for
374  *       use with Booleans.
375  *      @param  key     The preference key to read the Boolean from.
376  *      @param  domain  The bundle ID of the plug-in.
377  *      @param  result  A pointer to a Boolean type. Left unchanged if the value doesn't exist.
378  */
379 #define READ_GROWL_PREF_BOOL(key, domain, result) do {\
380         CFBooleanRef boolValue = NULL; \
381         READ_GROWL_PREF_VALUE(key, domain, CFBooleanRef, &boolValue); \
382         if (boolValue) {\
383                 *result = CFBooleanGetValue(boolValue); \
384                 CFRelease(boolValue); \
385         } } while(0)
386
387 /*!     @function    WRITE_GROWL_PREF_BOOL
388  *      @abstract    Writes the given Boolean to the plug-in's preferences.
389  *      @discussion  This is a wrapper around WRITE_GROWL_PREF_VALUE() intended for
390  *       use with Booleans.
391  *      @param  key     The preference key to write the Boolean for.
392  *      @param  value   The Boolean value to write to the preferences.
393  *      @param  domain  The bundle ID of the plug-in.
394  */
395 #define WRITE_GROWL_PREF_BOOL(key, value, domain) do {\
396         WRITE_GROWL_PREF_VALUE(key, value ? kCFBooleanTrue : kCFBooleanFalse, domain); } while(0)
397
398 /*!     @function    READ_GROWL_PREF_INT
399  *      @abstract    Reads the given integer from the plug-in's preferences.
400  *      @discussion  This is a wrapper around READ_GROWL_PREF_VALUE() intended for
401  *       use with integers.
402  *      @param  key     The preference key to read the integer from.
403  *      @param  domain  The bundle ID of the plug-in.
404  *      @param  result  A pointer to an integer. Leaves unchanged if the value doesn't exist.
405  */
406 #define READ_GROWL_PREF_INT(key, domain, result) do {\
407         CFNumberRef intValue = NULL; \
408         READ_GROWL_PREF_VALUE(key, domain, CFNumberRef, &intValue); \
409         if (intValue) {\
410                 CFNumberGetValue(intValue, kCFNumberIntType, result); \
411                 CFRelease(intValue); \
412         } } while(0)
413
414 /*!     @function    WRITE_GROWL_PREF_INT
415  *      @abstract    Writes the given integer to the plug-in's preferences.
416  *      @discussion  This is a wrapper around WRITE_GROWL_PREF_VALUE() intended for
417  *       use with integers.
418  *      @param  key     The preference key to write the integer for.
419  *      @param  value   The integer value to write to the preferences.
420  *      @param  domain  The bundle ID of the plug-in.
421  */
422 #define WRITE_GROWL_PREF_INT(key, value, domain) do {\
423         CFNumberRef intValue = CFNumberCreate(NULL, kCFNumberIntType, &value); \
424         WRITE_GROWL_PREF_VALUE(key, intValue, domain); \
425         CFRelease(intValue); } while(0)
426
427 /*!     @function    READ_GROWL_PREF_FLOAT
428  *      @abstract    Reads the given float from the plug-in's preferences.
429  *      @discussion  This is a wrapper around READ_GROWL_PREF_VALUE() intended for
430  *       use with floats.
431  *      @param  key     The preference key to read the float from.
432  *      @param  domain  The bundle ID of the plug-in.
433  *      @param  result  A pointer to a float. Leaves unchanged if the value doesn't exist.
434  */
435 #ifdef __LP64__
436 #define READ_GROWL_PREF_FLOAT(key, domain, result) do {\
437         CFNumberRef floatValue = NULL; \
438         READ_GROWL_PREF_VALUE(key, domain, CFNumberRef, &floatValue); \
439         if (floatValue) {\
440                 CFNumberGetValue(floatValue, kCFNumberCGFloatType, result); \
441                 CFRelease(floatValue); \
442         } } while(0)
443 #else
444 #define READ_GROWL_PREF_FLOAT(key, domain, result) do {\
445         CFNumberRef floatValue = NULL; \
446         READ_GROWL_PREF_VALUE(key, domain, CFNumberRef, &floatValue); \
447         if (floatValue) {\
448                 CFNumberGetValue(floatValue, kCFNumberFloatType, result); \
449                 CFRelease(floatValue); \
450         } } while(0)
451 #endif
452
453 /*!     @function    WRITE_GROWL_PREF_FLOAT
454  *      @abstract    Writes the given float to the plug-in's preferences.
455  *      @discussion  This is a wrapper around WRITE_GROWL_PREF_VALUE() intended for
456  *       use with floats.
457  *      @param  key     The preference key to write the float for.
458  *      @param  value   The float value to write to the preferences.
459  *      @param  domain  The bundle ID of the plug-in.
460  */
461 #ifdef __LP64__
462 #define WRITE_GROWL_PREF_FLOAT(key, value, domain) do {\
463         CFNumberRef floatValue = CFNumberCreate(NULL, kCFNumberCGFloatType, &value); \
464         WRITE_GROWL_PREF_VALUE(key, floatValue, domain); \
465         CFRelease(floatValue); } while(0)
466 #else
467 #define WRITE_GROWL_PREF_FLOAT(key, value, domain) do {\
468         CFNumberRef floatValue = CFNumberCreate(NULL, kCFNumberFloatType, &value); \
469         WRITE_GROWL_PREF_VALUE(key, floatValue, domain); \
470         CFRelease(floatValue); } while(0)
471 #endif
472
473
474 /*!     @defined        GROWL_CLOSE_ALL_NOTIFICATIONS
475  *      @abstract       Notification to close all Growl notifications
476  *      @discussion     Should be posted to the default notification center when a close widget is option+clicked.
477  *    All notifications should close in response. 
478  */
479 #define GROWL_CLOSE_ALL_NOTIFICATIONS XSTR("GrowlCloseAllNotifications")
480
481 #pragma mark Small utilities
482
483 /*!
484  * @defined FLOAT_EQ(x,y)
485  * @abstract Compares two floats.
486  */
487 #define FLOAT_EQ(x,y) (((y - FLT_EPSILON) < x) && (x < (y + FLT_EPSILON)))
488
489 #endif //ndef _GROWL_GROWLDEFINESINTERNAL_H