2 // GrowlDefinesInternal.h
5 // Created by Karl Adam on Mon May 17 2004.
6 // Copyright (c) 2004 the Growl Project. All rights reserved.
9 #ifndef _GROWL_GROWLDEFINESINTERNAL_H
10 #define _GROWL_GROWLDEFINESINTERNAL_H
12 #include <CoreFoundation/CoreFoundation.h>
13 #include <sys/types.h>
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.
27 * Notification keys (used in GrowlHelperApp, in GrowlApplicationBridge, and
28 * by applications that don't use GrowlApplicationBridge) are defined in
34 * @abstract Typedef to int so Growl will compile on pre-10.5 SDKs.
36 #ifndef NSINTEGER_DEFINED
37 typedef int NSInteger;
38 typedef unsigned int NSUInteger;
39 #define NSINTEGER_DEFINED
44 * @abstract Typedef to float so Growl will compile on pre-10.5 SDKs.
46 #ifndef CGFLOAT_DEFINED
47 typedef float CGFloat;
48 #define CGFLOAT_IS_DOUBLE 0
49 #define CGFLOAT_DEFINED
53 * @defined GrowlCGFloatCeiling()
54 * @abstract Macro for the ceil() function that uses a different precision depending on the CPU architecture.
57 * @defined GrowlCGFloatAbsoluteValue()
58 * @abstract Macro for the fabs() function that uses a different precision depending on the CPU architecture.
61 * @defined GrowlCGFloatFloor()
62 * @abstract Macro for the floor() function that uses a different precision depending on the CPU architecture.
65 #define GrowlCGFloatCeiling(x) ceil(x)
66 #define GrowlCGFloatAbsoluteValue(x) fabs(x)
67 #define GrowlCGFloatFloor(x) floor(x)
69 #define GrowlCGFloatCeiling(x) ceilf(x)
70 #define GrowlCGFloatAbsoluteValue(x) fabsf(x)
71 #define GrowlCGFloatFloor(x) floorf(x)
74 /*! @defined GROWL_TCP_PORT
75 * @abstract The TCP listen port for Growl notification servers.
77 #define GROWL_TCP_PORT 23052
79 /*! @defined GROWL_UDP_PORT
80 * @abstract The UDP listen port for Growl notification servers.
82 #define GROWL_UDP_PORT 9887
84 /*! @defined GROWL_PROTOCOL_VERSION
85 * @abstract The current version of the Growl network-notifications protocol (without encryption).
87 #define GROWL_PROTOCOL_VERSION 1
89 /*! @defined GROWL_PROTOCOL_VERSION_AES128
90 * @abstract The current version of the Growl network-notifications protocol (with AES-128 encryption).
92 #define GROWL_PROTOCOL_VERSION_AES128 2
94 /*! @defined GROWL_TYPE_REGISTRATION
95 * @abstract The packet type of registration packets with MD5 authentication.
97 #define GROWL_TYPE_REGISTRATION 0
98 /*! @defined GROWL_TYPE_NOTIFICATION
99 * @abstract The packet type of notification packets with MD5 authentication.
101 #define GROWL_TYPE_NOTIFICATION 1
102 /*! @defined GROWL_TYPE_REGISTRATION_SHA256
103 * @abstract The packet type of registration packets with SHA-256 authentication.
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.
109 #define GROWL_TYPE_NOTIFICATION_SHA256 3
110 /*! @defined GROWL_TYPE_REGISTRATION_NOAUTH
111 * @abstract The packet type of registration packets without authentication.
113 #define GROWL_TYPE_REGISTRATION_NOAUTH 4
114 /*! @defined GROWL_TYPE_NOTIFICATION_NOAUTH
115 * @abstract The packet type of notification packets without authentication.
117 #define GROWL_TYPE_NOTIFICATION_NOAUTH 5
119 #define ATTRIBUTE_PACKED __attribute((packed))
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.
125 struct GrowlNetworkPacket {
126 unsigned char version;
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.
141 struct GrowlNetworkRegistration {
142 struct GrowlNetworkPacket common;
143 /* This name is used both internally and in the Growl
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.
151 * In addition to being unsigned, the application name length is in
152 * network byte order.
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.
158 unsigned char numAllNotifications;
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.
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.
172 unsigned char data[];
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.
188 struct GrowlNetworkNotification {
189 struct GrowlNetworkPacket common;
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.
200 struct GrowlNetworkNotificationFlags {
201 #ifdef __BIG_ENDIAN__
202 unsigned reserved: 12;
208 unsigned reserved: 12;
210 } ATTRIBUTE_PACKED flags; //size = 16 (12 + 3 + 1)
212 /* In addition to being unsigned, the notification name length
213 * is in network byte order.
215 unsigned short nameLen;
216 /* @discussion In addition to being unsigned, the title length is in
217 * network byte order.
219 unsigned short titleLen;
220 /* In addition to being unsigned, the description length is in
221 * network byte order.
223 unsigned short descriptionLen;
224 /* In addition to being unsigned, the application name length
225 * is in network byte order.
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.
235 unsigned char data[];
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.
244 #define GrowlEnabledKey XSTR("GrowlEnabled")
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.
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.
256 #define GROWL_SCREENSHOT_MODE XSTR("ScreenshotMode")
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.
263 #define GROWL_APP_LOCATION XSTR("AppLocation")
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.
270 #define GROWL_REMOTE_ADDRESS XSTR("RemoteAddress")
273 * @defined GROWL_PREFPANE_BUNDLE_IDENTIFIER
274 * @discussion The bundle identifier for the Growl preference pane.
276 #define GROWL_PREFPANE_BUNDLE_IDENTIFIER XSTR("com.growl.prefpanel")
278 * @defined GROWL_HELPERAPP_BUNDLE_IDENTIFIER
279 * @discussion The bundle identifier for the Growl background application (GrowlHelperApp).
281 #define GROWL_HELPERAPP_BUNDLE_IDENTIFIER XSTR("com.Growl.GrowlHelperApp")
284 * @defined GROWL_PREFPANE_NAME
285 * @discussion The file name of the Growl preference pane.
287 #define GROWL_PREFPANE_NAME XSTR("Growl.prefPane")
288 #define PREFERENCE_PANES_SUBFOLDER_OF_LIBRARY XSTR("PreferencePanes")
289 #define PREFERENCE_PANE_EXTENSION XSTR("prefPane")
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")
297 /* --- These following macros are intended for plug-ins --- */
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).
304 #define SYNCHRONIZE_GROWL_PREFS() CFPreferencesAppSynchronize(CFSTR("com.Growl.GrowlHelperApp"))
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.
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); \
318 CFNotificationCenterPostNotification(CFNotificationCenterGetDistributedCenter(), \
319 CFSTR("GrowlPreferencesChanged"), \
320 CFSTR("GrowlUserDefaults"), \
322 CFRelease(userInfo); \
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.
335 * If the value is set, you are responsible for releasing it.
337 #define READ_GROWL_PREF_VALUE(key, domain, type, result) do {\
338 CFDictionaryRef prefs = (CFDictionaryRef)CFPreferencesCopyAppValue((CFStringRef)domain, \
339 CFSTR("com.Growl.GrowlHelperApp")); \
341 if (CFDictionaryContainsKey(prefs, key)) {\
342 *result = (type)CFDictionaryGetValue(prefs, key); \
345 CFRelease(prefs); } \
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.
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); \
364 prefs = CFDictionaryCreateMutableCopy(NULL, 0, staticPrefs); \
365 CFRelease(staticPrefs); \
367 CFDictionarySetValue(prefs, key, value); \
368 CFPreferencesSetAppValue((CFStringRef)domain, prefs, CFSTR("com.Growl.GrowlHelperApp")); \
369 CFRelease(prefs); } while(0)
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
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.
379 #define READ_GROWL_PREF_BOOL(key, domain, result) do {\
380 CFBooleanRef boolValue = NULL; \
381 READ_GROWL_PREF_VALUE(key, domain, CFBooleanRef, &boolValue); \
383 *result = CFBooleanGetValue(boolValue); \
384 CFRelease(boolValue); \
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
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.
395 #define WRITE_GROWL_PREF_BOOL(key, value, domain) do {\
396 WRITE_GROWL_PREF_VALUE(key, value ? kCFBooleanTrue : kCFBooleanFalse, domain); } while(0)
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
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.
406 #define READ_GROWL_PREF_INT(key, domain, result) do {\
407 CFNumberRef intValue = NULL; \
408 READ_GROWL_PREF_VALUE(key, domain, CFNumberRef, &intValue); \
410 CFNumberGetValue(intValue, kCFNumberIntType, result); \
411 CFRelease(intValue); \
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
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.
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)
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
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.
436 #define READ_GROWL_PREF_FLOAT(key, domain, result) do {\
437 CFNumberRef floatValue = NULL; \
438 READ_GROWL_PREF_VALUE(key, domain, CFNumberRef, &floatValue); \
440 CFNumberGetValue(floatValue, kCFNumberCGFloatType, result); \
441 CFRelease(floatValue); \
444 #define READ_GROWL_PREF_FLOAT(key, domain, result) do {\
445 CFNumberRef floatValue = NULL; \
446 READ_GROWL_PREF_VALUE(key, domain, CFNumberRef, &floatValue); \
448 CFNumberGetValue(floatValue, kCFNumberFloatType, result); \
449 CFRelease(floatValue); \
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
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.
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)
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)
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.
479 #define GROWL_CLOSE_ALL_NOTIFICATIONS XSTR("GrowlCloseAllNotifications")
481 #pragma mark Small utilities
484 * @defined FLOAT_EQ(x,y)
485 * @abstract Compares two floats.
487 #define FLOAT_EQ(x,y) (((y - FLT_EPSILON) < x) && (x < (y + FLT_EPSILON)))
489 #endif //ndef _GROWL_GROWLDEFINESINTERNAL_H