From d61750f591c9979617e40dcba3a6f2d38d5b7be9 Mon Sep 17 00:00:00 2001 From: dynaflash Date: Fri, 27 Apr 2007 15:53:56 +0000 Subject: [PATCH] macGui: Growl Support initial implementation - include Growl.framework in xcode project - Growl notify when encode is done - fix cancelled encode finished bug - may want a user pref to let them select if they want a notification and what type, on screen or grow. or both - right now, its both. git-svn-id: svn://svn.handbrake.fr/HandBrake/trunk@554 b64f7644-9d1e-0410-96f1-a4d463321fa5 --- macosx/Controller.h | 12 +- macosx/Controller.mm | 72 +- macosx/Growl.framework/Growl | 1 + macosx/Growl.framework/Headers | 1 + macosx/Growl.framework/Resources | 1 + macosx/Growl.framework/Versions/A/Growl | Bin 0 -> 140048 bytes .../Versions/A/Headers/Growl.h | 6 + .../A/Headers/GrowlApplicationBridge-Carbon.h | 758 ++++++++++++++++++ .../A/Headers/GrowlApplicationBridge.h | 556 +++++++++++++ .../Versions/A/Headers/GrowlDefines.h | 307 +++++++ .../Versions/A/Resources/Info.plist | 24 + macosx/Growl.framework/Versions/Current | 1 + macosx/HandBrake.xcodeproj/project.pbxproj | 43 +- 13 files changed, 1766 insertions(+), 16 deletions(-) create mode 120000 macosx/Growl.framework/Growl create mode 120000 macosx/Growl.framework/Headers create mode 120000 macosx/Growl.framework/Resources create mode 100755 macosx/Growl.framework/Versions/A/Growl create mode 100644 macosx/Growl.framework/Versions/A/Headers/Growl.h create mode 100644 macosx/Growl.framework/Versions/A/Headers/GrowlApplicationBridge-Carbon.h create mode 100644 macosx/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h create mode 100644 macosx/Growl.framework/Versions/A/Headers/GrowlDefines.h create mode 100644 macosx/Growl.framework/Versions/A/Resources/Info.plist create mode 120000 macosx/Growl.framework/Versions/Current diff --git a/macosx/Controller.h b/macosx/Controller.h index 2d8ed1be8..49e939ffc 100644 --- a/macosx/Controller.h +++ b/macosx/Controller.h @@ -5,21 +5,23 @@ It may be used under the terms of the GNU General Public License. */ #include +#include #include "hb.h" + #include "ChapterTitles.h" #include "ScanController.h" #include "PictureController.h" #include "QueueController.h" -@interface HBController : NSObject +@interface HBController : NSObject { IBOutlet NSWindow * fWindow; /* Scan panel */ - IBOutlet ScanController * fScanController; + IBOutlet ScanController * fScanController; IBOutlet NSPanel * fScanPanel; /* Picture panel */ @@ -158,6 +160,9 @@ IBOutlet NSButton * fPresetsDelete; hb_handle_t * fHandle; hb_title_t * fTitle; + /* integer to set to determine the previous state + of encode 0==idle, 1==encoding, 2==cancelled*/ + int fEncodeState; } - (void) TranslateStrings; @@ -249,6 +254,9 @@ willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex; +// Growl methods +- (NSDictionary *) registrationDictionaryForGrowl; +-(IBAction)showGrowlDoneNotification:(id)sender; @end diff --git a/macosx/Controller.mm b/macosx/Controller.mm index 8bfd7cb23..7caaf7fac 100644 --- a/macosx/Controller.mm +++ b/macosx/Controller.mm @@ -9,6 +9,10 @@ #define _(a) NSLocalizedString(a,NULL) + + + + static int FormatSettings[3][4] = { { HB_MUX_MP4 | HB_VCODEC_FFMPEG | HB_ACODEC_FAAC, HB_MUX_MP4 | HB_VCODEC_X264 | HB_ACODEC_FAAC, @@ -37,13 +41,18 @@ static int FormatSettings[3][4] = - (void) applicationDidFinishLaunching: (NSNotification *) notification { + + int build; char * version; + /* Init libhb */ fHandle = hb_init( HB_DEBUG_NONE, [[NSUserDefaults standardUserDefaults] boolForKey:@"CheckForUpdates"] ); - + /* Set the Growl Delegate */ + HBController *hbGrowlDelegate = [[HBController alloc] init]; + [GrowlApplicationBridge setGrowlDelegate: hbGrowlDelegate]; /* Init others controllers */ [fScanController SetHandle: fHandle]; [fPictureController SetHandle: fHandle]; @@ -97,7 +106,9 @@ static int FormatSettings[3][4] = [self TranslateStrings]; - /* Init User Presets .plist */ + +//[self registrationDictionaryForGrowl]; +/* Init User Presets .plist */ /* We declare the default NSFileManager into fileManager */ NSFileManager * fileManager = [NSFileManager defaultManager]; //presetPrefs = [[NSUserDefaults standardUserDefaults] retain]; @@ -225,7 +236,18 @@ static int FormatSettings[3][4] = } +// register a test notification and make +// it enabled by default +#define SERVICE_NAME @"Encode Done" +- (NSDictionary *)registrationDictionaryForGrowl +{ +NSDictionary *registrationDictionary = [NSDictionary dictionaryWithObjectsAndKeys: +[NSArray arrayWithObjects:SERVICE_NAME,nil], GROWL_NOTIFICATIONS_ALL, +[NSArray arrayWithObjects:SERVICE_NAME,nil], GROWL_NOTIFICATIONS_DEFAULT, +nil]; +return registrationDictionary; +} - (void) TranslateStrings { [fSrcDVD1Field setStringValue: _( @"DVD:" )]; @@ -543,15 +565,27 @@ static int FormatSettings[3][4] = hb_rem( fHandle, job ); } - /* Lets alert the user that the encode has finished */ - int status; - NSBeep(); - status = NSRunAlertPanel(@"Put down that cocktail...",@"your HandBrake encode is done!", @"OK", nil, nil); - if ( status == NSAlertDefaultReturn ) + if (fEncodeState != 2) // if the encode has not been cancelled + { + /* Lets alert the user that the encode has finished */ + /*Growl Notification*/ + [self showGrowlDoneNotification: NULL]; + /*On Screen Notification*/ + int status; + NSBeep(); + status = NSRunAlertPanel(@"Put down that cocktail...",@"your HandBrake encode is done!", @"OK", nil, nil); + //[NSApp requestUserAttention:NSInformationalRequest]; + [NSApp requestUserAttention:NSCriticalRequest]; + if ( status == NSAlertDefaultReturn ) + { + [self EnableUI: YES]; + } + } + else { - [self EnableUI: YES]; + [self EnableUI: YES]; } - break; + break; } } @@ -576,6 +610,20 @@ static int FormatSettings[3][4] = forMode: NSModalPanelRunLoopMode]; } +-(IBAction)showGrowlDoneNotification:(id)sender +{ + + + [GrowlApplicationBridge + notifyWithTitle:@"Put down that cocktail..." + description:@"Thank You for using HandBrake" + notificationName:SERVICE_NAME + iconData:nil + priority:0 + isSticky:1 + clickContext:nil]; +} + - (void) EnableUI: (bool) b { NSControl * controls[] = @@ -748,7 +796,7 @@ static int FormatSettings[3][4] = hb_title_t * title = (hb_title_t *) hb_list_item( list, [fSrcTitlePopUp indexOfSelectedItem] ); hb_job_t * job = title->job; - int i; + //int i; /* Chapter selection */ job->chapter_start = [fSrcChapterStartPopUp indexOfSelectedItem] + 1; @@ -1016,6 +1064,8 @@ static int FormatSettings[3][4] = { /* Let libhb do the job */ hb_start( fHandle ); + /*set the fEncodeState State */ + fEncodeState = 1; /* Disable interface */ [self EnableUI: NO]; @@ -1039,6 +1089,8 @@ static int FormatSettings[3][4] = hb_stop( fHandle ); [fPauseButton setEnabled: NO]; [fRipButton setEnabled: NO]; + /*set the fEncodeState State */ + fEncodeState = 2; } } diff --git a/macosx/Growl.framework/Growl b/macosx/Growl.framework/Growl new file mode 120000 index 000000000..85956e2d2 --- /dev/null +++ b/macosx/Growl.framework/Growl @@ -0,0 +1 @@ +Versions/Current/Growl \ No newline at end of file diff --git a/macosx/Growl.framework/Headers b/macosx/Growl.framework/Headers new file mode 120000 index 000000000..a177d2a6b --- /dev/null +++ b/macosx/Growl.framework/Headers @@ -0,0 +1 @@ +Versions/Current/Headers \ No newline at end of file diff --git a/macosx/Growl.framework/Resources b/macosx/Growl.framework/Resources new file mode 120000 index 000000000..953ee36f3 --- /dev/null +++ b/macosx/Growl.framework/Resources @@ -0,0 +1 @@ +Versions/Current/Resources \ No newline at end of file diff --git a/macosx/Growl.framework/Versions/A/Growl b/macosx/Growl.framework/Versions/A/Growl new file mode 100755 index 0000000000000000000000000000000000000000..a0572a332e2a96e1a4a21b5688b1bd4b9688ea92 GIT binary patch literal 140048 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%0D*`E(XOD@)Z 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 literal 0 HcmV?d00001 diff --git a/macosx/Growl.framework/Versions/A/Headers/Growl.h b/macosx/Growl.framework/Versions/A/Headers/Growl.h new file mode 100644 index 000000000..e2a44255d --- /dev/null +++ b/macosx/Growl.framework/Versions/A/Headers/Growl.h @@ -0,0 +1,6 @@ +#include "GrowlDefines.h" + +#ifdef __OBJC__ +# include "GrowlApplicationBridge.h" +#endif +#include "GrowlApplicationBridge-Carbon.h" diff --git a/macosx/Growl.framework/Versions/A/Headers/GrowlApplicationBridge-Carbon.h b/macosx/Growl.framework/Versions/A/Headers/GrowlApplicationBridge-Carbon.h new file mode 100644 index 000000000..fb705097f --- /dev/null +++ b/macosx/Growl.framework/Versions/A/Headers/GrowlApplicationBridge-Carbon.h @@ -0,0 +1,758 @@ +// +// GrowlApplicationBridge-Carbon.h +// Growl +// +// Created by Mac-arena the Bored Zo on Wed Jun 18 2004. +// Based on GrowlApplicationBridge.h by Evan Schoenberg. +// This source code is in the public domain. You may freely link it into any +// program. +// + +#ifndef _GROWLAPPLICATIONBRIDGE_CARBON_H_ +#define _GROWLAPPLICATIONBRIDGE_CARBON_H_ + +#include +#include + +/*! @header GrowlApplicationBridge-Carbon.h + * @abstract Declares an API that Carbon applications can use to interact with Growl. + * @discussion GrowlApplicationBridge uses a delegate to provide information //XXX + * to Growl (such as your application's name and what notifications it may + * post) and to provide information to your application (such as that Growl + * is listening for notifications or that a notification has been clicked). + * + * You can set the Growldelegate with Growl_SetDelegate and find out the + * current delegate with Growl_GetDelegate. See struct Growl_Delegate for more + * information about the delegate. + */ + +__BEGIN_DECLS + +/*! @struct Growl_Delegate + * @abstract Delegate to supply GrowlApplicationBridge with information and respond to events. + * @discussion The Growl delegate provides your interface to + * GrowlApplicationBridge. When GrowlApplicationBridge needs information about + * your application, it looks for it in the delegate; when Growl or the user + * does something that you might be interested in, GrowlApplicationBridge + * looks for a callback in the delegate and calls it if present + * (meaning, if it is not NULL). + * XXX on all of that + * @field size The size of the delegate structure. + * @field applicationName The name of your application. + * @field registrationDictionary A dictionary describing your application and the notifications it can send out. + * @field applicationIconData Your application's icon. + * @field growlInstallationWindowTitle The title of the installation window. + * @field growlInstallationInformation Text to display in the installation window. + * @field growlUpdateWindowTitle The title of the update window. + * @field growlUpdateInformation Text to display in the update window. + * @field referenceCount A count of owners of the delegate. + * @field retain Called when GrowlApplicationBridge receives this delegate. + * @field release Called when GrowlApplicationBridge no longer needs this delegate. + * @field growlIsReady Called when GrowlHelperApp is listening for notifications. + * @field growlNotificationWasClicked Called when a Growl notification is clicked. + * @field growlNotificationTimedOut Called when a Growl notification timed out. + */ +struct Growl_Delegate { + /* @discussion This should be sizeof(struct Growl_Delegate). + */ + size_t size; + + /*All of these attributes are optional. + *Optional attributes can be NULL; required attributes that + * are NULL cause setting the Growl delegate to fail. + *XXX - move optional/required status into the discussion for each field + */ + + /* This name is used both internally and in the Growl preferences. + * + * This should remain stable between different versions and incarnations of + * your application. + * For example, "SurfWriter" is a good app name, whereas "SurfWriter 2.0" and + * "SurfWriter Lite" are not. + * + * This can be NULL if it is provided elsewhere, namely in an + * auto-discoverable plist file in your app bundle + * (XXX refer to more information on that) or in registrationDictionary. + */ + CFStringRef applicationName; + + /* + * Must contain at least these keys: + * GROWL_NOTIFICATIONS_ALL (CFArray): + * Contains the names of all notifications your application may post. + * + * Can also contain these keys: + * GROWL_NOTIFICATIONS_DEFAULT (CFArray): + * Names of notifications that should be enabled by default. + * If omitted, GROWL_NOTIFICATIONS_ALL will be used. + * GROWL_APP_NAME (CFString): + * Same as the applicationName member of this structure. + * If both are present, the applicationName member shall prevail. + * If this key is present, you may omit applicationName (set it to NULL). + * GROWL_APP_ICON (CFData): + * Same as the iconData member of this structure. + * If both are present, the iconData member shall prevail. + * If this key is present, you may omit iconData (set it to NULL). + * + * If you change the contents of this dictionary after setting the delegate, + * be sure to call Growl_Reregister. + * + * This can be NULL if you have an auto-discoverable plist file in your app + * bundle. (XXX refer to more information on that) + */ + CFDictionaryRef registrationDictionary; + + /* The data can be in any format supported by NSImage. As of + * Mac OS X 10.3, this includes the .icns, TIFF, JPEG, GIF, PNG, PDF, and + * PICT formats. + * + * If this is not supplied, Growl will look up your application's icon by + * its application name. + */ + CFDataRef applicationIconData; + + /* Installer display attributes + * + * These four attributes are used by the Growl installer, if this framework + * supports it. + * For any of these being NULL, a localised default will be + * supplied. + */ + + /* If this is NULL, Growl will use a default, + * localized title. + * + * Only used if you're using Growl-WithInstaller.framework. Otherwise, + * this member is ignored. + */ + CFStringRef growlInstallationWindowTitle; + /* This information may be as long or short as desired (the + * window will be sized to fit it). If Growl is not installed, it will + * be displayed to the user as an explanation of what Growl is and what + * it can do in your application. + * It should probably note that no download is required to install. + * + * If this is NULL, Growl will use a default, localized + * explanation. + * + * Only used if you're using Growl-WithInstaller.framework. Otherwise, + * this member is ignored. + */ + CFStringRef growlInstallationInformation; + /* If this is NULL, Growl will use a default, + * localized title. + * + * Only used if you're using Growl-WithInstaller.framework. Otherwise, + * this member is ignored. + */ + CFStringRef growlUpdateWindowTitle; + /* This information may be as long or short as desired (the + * window will be sized to fit it). If an older version of Growl is + * installed, it will be displayed to the user as an explanation that an + * updated version of Growl is included in your application and + * no download is required. + * + * If this is NULL, Growl will use a default, localized + * explanation. + * + * Only used if you're using Growl-WithInstaller.framework. Otherwise, + * this member is ignored. + */ + CFStringRef growlUpdateInformation; + + /* This member is provided for use by your retain and release + * callbacks (see below). + * + * GrowlApplicationBridge never directly uses this member. Instead, it + * calls your retain callback (if non-NULL) and your release + * callback (if non-NULL). + */ + unsigned referenceCount; + + //Functions. Currently all of these are optional (any of them can be NULL). + + /* When you call Growl_SetDelegate(newDelegate), it will call + * oldDelegate->release(oldDelegate), and then it will call + * newDelegate->retain(newDelegate), and the return value from retain + * is what will be set as the delegate. + * (This means that this member works like CFRetain and -[NSObject retain].) + * This member is optional (it can be NULL). + * For a delegate allocated with malloc, this member would be + * NULL. + * @result A delegate to which GrowlApplicationBridge holds a reference. + */ + void *(*retain)(void *); + /* When you call Growl_SetDelegate(newDelegate), it will call + * oldDelegate->release(oldDelegate), and then it will call + * newDelegate->retain(newDelegate), and the return value from retain + * is what will be set as the delegate. + * (This means that this member works like CFRelease and + * -[NSObject release].) + * This member is optional (it can be NULL). + * For a delegate allocated with malloc, this member might be + * free(3). + */ + void (*release)(void *); + + /* Informs the delegate that Growl (specifically, the GrowlHelperApp) was + * launched successfully (or was already running). The application can + * take actions with the knowledge that Growl is installed and functional. + */ + void (*growlIsReady)(void); + + /* Informs the delegate that a Growl notification was clicked. It is only + * sent for notifications sent with a non-NULL clickContext, + * so if you want to receive a message when a notification is clicked, + * clickContext must not be NULL when calling + * Growl_PostNotification or + * Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext. + */ + void (*growlNotificationWasClicked)(CFPropertyListRef clickContext); + + /* Informs the delegate that a Growl notification timed out. It is only + * sent for notifications sent with a non-NULL clickContext, + * so if you want to receive a message when a notification is clicked, + * clickContext must not be NULL when calling + * Growl_PostNotification or + * Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext. + */ + void (*growlNotificationTimedOut)(CFPropertyListRef clickContext); +}; + +/*! @struct Growl_Notification + * @abstract Structure describing a Growl notification. + * @discussion XXX + * @field size The size of the notification structure. + * @field name Identifies the notification. + * @field title Short synopsis of the notification. + * @field description Additional text. + * @field iconData An icon for the notification. + * @field priority An indicator of the notification's importance. + * @field reserved Bits reserved for future usage. + * @field isSticky Requests that a notification stay on-screen until dismissed explicitly. + * @field clickContext An identifier to be passed to your click callback when a notification is clicked. + * @field clickCallback A callback to call when the notification is clicked. + */ +struct Growl_Notification { + /* This should be sizeof(struct Growl_Notification). + */ + size_t size; + + /* The notification name distinguishes one type of + * notification from another. The name should be human-readable, as it + * will be displayed in the Growl preference pane. + * + * The name is used in the GROWL_NOTIFICATIONS_ALL and + * GROWL_NOTIFICATIONS_DEFAULT arrays in the registration dictionary, and + * in this member of the Growl_Notification structure. + */ + CFStringRef name; + + /* A notification's title describes the notification briefly. + * It should be easy to read quickly by the user. + */ + CFStringRef title; + + /* The description supplements the title with more + * information. It is usually longer and sometimes involves a list of + * subjects. For example, for a 'Download complete' notification, the + * description might have one filename per line. GrowlMail in Growl 0.6 + * uses a description of '%d new mail(s)' (formatted with the number of + * messages). + */ + CFStringRef description; + + /* The notification icon usually indicates either what + * happened (it may have the same icon as e.g. a toolbar item that + * started the process that led to the notification), or what it happened + * to (e.g. a document icon). + * + * The icon data is optional, so it can be NULL. In that + * case, the application icon is used alone. Not all displays support + * icons. + * + * The data can be in any format supported by NSImage. As of Mac OS X + * 10.3, this includes the .icns, TIFF, JPEG, GIF, PNG, PDF, and PICT form + * ats. + */ + CFDataRef iconData; + + /* Priority is new in Growl 0.6, and is represented as a + * signed integer from -2 to +2. 0 is Normal priority, -2 is Very Low + * priority, and +2 is Very High priority. + * + * Not all displays support priority. If you do not wish to assign a + * priority to your notification, assign 0. + */ + signed int priority; + + /* These bits are not used in Growl 0.6. Set them to 0. + */ + unsigned reserved: 31; + + /* When the sticky bit is clear, in most displays, + * notifications disappear after a certain amount of time. Sticky + * notifications, however, remain on-screen until the user dismisses them + * explicitly, usually by clicking them. + * + * Sticky notifications were introduced in Growl 0.6. Most notifications + * should not be sticky. Not all displays support sticky notifications, + * and the user may choose in Growl's preference pane to force the + * notification to be sticky or non-sticky, in which case the sticky bit + * in the notification will be ignored. + */ + unsigned isSticky: 1; + + /* If this is not NULL, and your click callback + * is not NULL either, this will be passed to the callback + * when your notification is clicked by the user. + * + * Click feedback was introduced in Growl 0.6, and it is optional. Not + * all displays support click feedback. + */ + CFPropertyListRef clickContext; + + /* If this is not NULL, it will be called instead + * of the Growl delegate's click callback when clickContext is + * non-NULL and the notification is clicked on by the user. + * + * Click feedback was introduced in Growl 0.6, and it is optional. Not + * all displays support click feedback. + * + * The per-notification click callback is not yet supported as of Growl + * 0.7. + */ + void (*clickCallback)(CFPropertyListRef clickContext); +}; + +#pragma mark - +#pragma mark Easy initialisers + +/*! @defined InitGrowlDelegate + * @abstract Callable macro. Initializes a Growl delegate structure to defaults. + * @discussion Call with a pointer to a struct Growl_Delegate. All of the + * members of the structure will be set to 0 or NULL, except for + * size (which will be set to sizeof(struct Growl_Delegate)) and + * referenceCount (which will be set to 1). + */ +#define InitGrowlDelegate(delegate) \ + do { \ + if (delegate) { \ + (delegate)->size = sizeof(struct Growl_Delegate); \ + (delegate)->applicationName = NULL; \ + (delegate)->registrationDictionary = NULL; \ + (delegate)->applicationIconData = NULL; \ + (delegate)->growlInstallationWindowTitle = NULL; \ + (delegate)->growlInstallationInformation = NULL; \ + (delegate)->growlUpdateWindowTitle = NULL; \ + (delegate)->growlUpdateInformation = NULL; \ + (delegate)->referenceCount = 1U; \ + (delegate)->retain = NULL; \ + (delegate)->release = NULL; \ + (delegate)->growlIsReady = NULL; \ + (delegate)->growlNotificationWasClicked = NULL; \ + (delegate)->growlNotificationTimedOut = NULL; \ + } \ + } while(0) + +/*! @defined InitGrowlNotification + * @abstract Callable macro. Initializes a Growl notification structure to defaults. + * @discussion Call with a pointer to a struct Growl_Notification. All of + * the members of the structure will be set to 0 or NULL, except + * for size (which will be set to + * sizeof(struct Growl_Notification)). + */ +#define InitGrowlNotification(notification) \ + do { \ + if (notification) { \ + (notification)->size = sizeof(struct Growl_Notification); \ + (notification)->name = NULL; \ + (notification)->title = NULL; \ + (notification)->description = NULL; \ + (notification)->iconData = NULL; \ + (notification)->priority = 0; \ + (notification)->reserved = 0U; \ + (notification)->isSticky = false; \ + (notification)->clickContext = NULL; \ + } \ + } while(0) + +#pragma mark - +#pragma mark Public API + +// @functiongroup Managing the Growl delegate + +/*! @function Growl_SetDelegate + * @abstract Replaces the current Growl delegate with a new one, or removes + * the Growl delegate. + * @param newDelegate + * @result Returns false and does nothing else if a pointer that was passed in + * is unsatisfactory (because it is non-NULL, but at least one + * required member of it is NULL). Otherwise, sets or unsets the + * delegate and returns true. + * @discussion When newDelegate is non-NULL, sets + * the delegate to newDelegate. When it is NULL, + * the current delegate will be unset, and no delegate will be in place. + * + * It is legal for newDelegate to be the current delegate; + * nothing will happen, and Growl_SetDelegate will return true. It is also + * legal for it to be NULL, as described above; again, it will + * return true. + * + * If there was a delegate in place before the call, Growl_SetDelegate will + * call the old delegate's release member if it was non-NULL. If + * newDelegate is non-NULL, Growl_SetDelegate will + * call newDelegate->retain, and set the delegate to its return + * value. + * + * If you are using Growl-WithInstaller.framework, and an older version of + * Growl is installed on the user's system, the user will automatically be + * prompted to update. + * + * GrowlApplicationBridge currently does not copy this structure, nor does it + * retain any of the CF objects in the structure (it regards the structure as + * a container that retains the objects when they are added and releases them + * when they are removed or the structure is destroyed). Also, + * GrowlApplicationBridge currently does not modify any member of the + * structure, except possibly the referenceCount by calling the retain and + * release members. + */ +Boolean Growl_SetDelegate(struct Growl_Delegate *newDelegate); + +/*! @function Growl_GetDelegate + * @abstract Returns the current Growl delegate, if any. + * @result The current Growl delegate. + * @discussion Returns the last pointer passed into Growl_SetDelegate, or + * NULL if no such call has been made. + * + * This function follows standard Core Foundation reference-counting rules. + * Because it is a Get function, not a Copy function, it will not retain the + * delegate on your behalf. You are responsible for retaining and releasing + * the delegate as needed. + */ +struct Growl_Delegate *Growl_GetDelegate(void); + +#pragma mark - + +// @functiongroup Posting Growl notifications + +/*! @function Growl_PostNotification + * @abstract Posts a Growl notification. + * @param notification The notification to post. + * @discussion This is the preferred means for sending a Growl notification. + * The notification name and at least one of the title and description are + * required (all three are preferred). All other parameters may be + * NULL (or 0 or false as appropriate) to accept default values. + * + * If using the Growl-WithInstaller framework, if Growl is not installed the + * user will be prompted to install Growl. + * If the user cancels, this function will have no effect until the next + * application session, at which time when it is called the user will be + * prompted again. The user is also given the option to not be prompted again. + * If the user does choose to install Growl, the requested notification will + * be displayed once Growl is installed and running. + */ +void Growl_PostNotification(const struct Growl_Notification *notification); + +/*! @function Growl_PostNotificationWithDictionary +* @abstract Notifies using a userInfo dictionary suitable for passing to +* CFDistributedNotificationCenter. +* @param userInfo The dictionary to notify with. +* @discussion Before Growl 0.6, your application would have posted +* notifications using CFDistributedNotificationCenter by creating a userInfo +* dictionary with the notification data. This had the advantage of allowing +* you to add other data to the dictionary for programs besides Growl that +* might be listening. +* +* This function allows you to use such dictionaries without being restricted +* to using CFDistributedNotificationCenter. The keys for this dictionary + * can be found in GrowlDefines.h. +*/ +void Growl_PostNotificationWithDictionary(CFDictionaryRef userInfo); + +/*! @function Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext + * @abstract Posts a Growl notification using parameter values. + * @param title The title of the notification. + * @param description The description of the notification. + * @param notificationName The name of the notification as listed in the + * registration dictionary. + * @param iconData Data representing a notification icon. Can be NULL. + * @param priority The priority of the notification (-2 to +2, with -2 + * being Very Low and +2 being Very High). + * @param isSticky If true, requests that this notification wait for a + * response from the user. + * @param clickContext An object to pass to the clickCallback, if any. Can + * be NULL, in which case the clickCallback is not called. + * @discussion Creates a temporary Growl_Notification, fills it out with the + * supplied information, and calls Growl_PostNotification on it. + * See struct Growl_Notification and Growl_PostNotification for more + * information. + * + * The icon data can be in any format supported by NSImage. As of Mac OS X + * 10.3, this includes the .icns, TIFF, JPEG, GIF, PNG, PDF, and PICT formats. + */ +void Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext( + /*inhale*/ + CFStringRef title, + CFStringRef description, + CFStringRef notificationName, + CFDataRef iconData, + signed int priority, + Boolean isSticky, + CFPropertyListRef clickContext); + +#pragma mark - + +// @functiongroup Registering + +/*! @function Growl_RegisterWithDictionary + * @abstract Register your application with Growl without setting a delegate. + * @discussion When you call this function with a dictionary, + * GrowlApplicationBridge registers your application using that dictionary. + * If you pass NULL, GrowlApplicationBridge will ask the delegate + * (if there is one) for a dictionary, and if that doesn't work, it will look + * in your application's bundle for an auto-discoverable plist. + * (XXX refer to more information on that) + * + * If you pass a dictionary to this function, it must include the + * GROWL_APP_NAME key, unless a delegate is set. + * + * This function is mainly an alternative to the delegate system introduced + * with Growl 0.6. Without a delegate, you cannot receive callbacks such as + * growlIsReady (since they are sent to the delegate). You can, + * however, set a delegate after registering without one. + * + * This function was introduced in Growl.framework 0.7. + * @result false if registration failed (e.g. if Growl isn't installed). + */ +Boolean Growl_RegisterWithDictionary(CFDictionaryRef regDict); + +/*! @function Growl_Reregister + * @abstract Updates your registration with Growl. + * @discussion If your application changes the contents of the + * GROWL_NOTIFICATIONS_ALL key in the registrationDictionary member of the + * Growl delegate, or if it changes the value of that member, or if it + * changes the contents of its auto-discoverable plist, call this function + * to have Growl update its registration information for your application. + * + * Otherwise, this function does not normally need to be called. If you're + * using a delegate, your application will be registered when you set the + * delegate if both the delegate and its registrationDictionary member are + * non-NULL. + * + * This function is now implemented using + * Growl_RegisterWithDictionary. + */ +void Growl_Reregister(void); + +#pragma mark - + +/*! @function Growl_SetWillRegisterWhenGrowlIsReady + * @abstract Tells GrowlApplicationBridge to register with Growl when Growl + * launches (or not). + * @discussion When Growl has started listening for notifications, it posts a + * GROWL_IS_READY notification on the Distributed Notification + * Center. GrowlApplicationBridge listens for this notification, using it to + * perform various tasks (such as calling your delegate's + * growlIsReady callback, if it has one). If this function is + * called with true, one of those tasks will be to reregister + * with Growl (in the manner of Growl_Reregister). + * + * This attribute is automatically set back to false + * (the default) after every GROWL_IS_READY notification. + * @param flag true if you want GrowlApplicationBridge to register with + * Growl when next it is ready; false if not. + */ +void Growl_SetWillRegisterWhenGrowlIsReady(Boolean flag); +/*! @function Growl_WillRegisterWhenGrowlIsReady + * @abstract Reports whether GrowlApplicationBridge will register with Growl + * when Growl next launches. + * @result true if GrowlApplicationBridge will register with + * Growl when next it posts GROWL_IS_READY; false if not. + */ +Boolean Growl_WillRegisterWhenGrowlIsReady(void); + +#pragma mark - + +// @functiongroup Obtaining registration dictionaries + +/*! @function Growl_CopyRegistrationDictionaryFromDelegate + * @abstract Asks the delegate for a registration dictionary. + * @discussion If no delegate is set, or if the delegate's + * registrationDictionary member is NULL, this + * function returns NULL. + * + * This function does not attempt to clean up the dictionary in any way - for + * example, if it is missing the GROWL_APP_NAME key, the result + * will be missing it too. Use + * Growl_CreateRegistrationDictionaryByFillingInDictionary: or + * Growl_CreateRegistrationDictionaryByFillingInDictionaryRestrictedToKeys + * to try to fill in missing keys. + * + * This function was introduced in Growl.framework 0.7. + * @result A registration dictionary. + */ +CFDictionaryRef Growl_CopyRegistrationDictionaryFromDelegate(void); + +/*! @function Growl_CopyRegistrationDictionaryFromBundle + * @abstract Looks in a bundle for a registration dictionary. + * @discussion This function looks in a bundle for an auto-discoverable + * registration dictionary file using CFBundleCopyResourceURL. + * If it finds one, it loads the file using CFPropertyList and + * returns the result. + * + * If you pass NULL as the bundle, the main bundle is examined. + * + * This function does not attempt to clean up the dictionary in any way - for + * example, if it is missing the GROWL_APP_NAME key, the result + * will be missing it too. Use + * Growl_CreateRegistrationDictionaryByFillingInDictionary: or + * Growl_CreateRegistrationDictionaryByFillingInDictionaryRestrictedToKeys + * to try to fill in missing keys. + * + * This function was introduced in Growl.framework 0.7. + * @result A registration dictionary. + */ +CFDictionaryRef Growl_CopyRegistrationDictionaryFromBundle(CFBundleRef bundle); + +/*! @function Growl_CreateBestRegistrationDictionary + * @abstract Obtains a registration dictionary, filled out to the best of + * GrowlApplicationBridge's knowledge. + * @discussion This function creates a registration dictionary as best + * GrowlApplicationBridge knows how. + * + * First, GrowlApplicationBridge examines the Growl delegate (if there is + * one) and gets the registration dictionary from that. If no such dictionary + * was obtained, GrowlApplicationBridge looks in your application's main + * bundle for an auto-discoverable registration dictionary file. If that + * doesn't exist either, this function returns NULL. + * + * Second, GrowlApplicationBridge calls + * Growl_CreateRegistrationDictionaryByFillingInDictionary with + * whatever dictionary was obtained. The result of that function is the + * result of this function. + * + * GrowlApplicationBridge uses this function when you call + * Growl_SetDelegate, or when you call + * Growl_RegisterWithDictionary with NULL. + * + * This function was introduced in Growl.framework 0.7. + * @result A registration dictionary. + */ +CFDictionaryRef Growl_CreateBestRegistrationDictionary(void); + +#pragma mark - + +// @functiongroup Filling in registration dictionaries + +/*! @function Growl_CreateRegistrationDictionaryByFillingInDictionary + * @abstract Tries to fill in missing keys in a registration dictionary. + * @param regDict The dictionary to fill in. + * @result The dictionary with the keys filled in. + * @discussion This function examines the passed-in dictionary for missing keys, + * and tries to work out correct values for them. As of 0.7, it uses: + * + * Key Value + * --- ----- + * GROWL_APP_NAME CFBundleExecutableName + * GROWL_APP_ICON The icon of the application. + * GROWL_APP_LOCATION The location of the application. + * GROWL_NOTIFICATIONS_DEFAULT GROWL_NOTIFICATIONS_ALL + * + * Keys are only filled in if missing; if a key is present in the dictionary, + * its value will not be changed. + * + * This function was introduced in Growl.framework 0.7. + */ +CFDictionaryRef Growl_CreateRegistrationDictionaryByFillingInDictionary(CFDictionaryRef regDict); +/*! @function Growl_CreateRegistrationDictionaryByFillingInDictionaryRestrictedToKeys + * @abstract Tries to fill in missing keys in a registration dictionary. + * @param regDict The dictionary to fill in. + * @param keys The keys to fill in. If NULL, any missing keys are filled in. + * @result The dictionary with the keys filled in. + * @discussion This function examines the passed-in dictionary for missing keys, + * and tries to work out correct values for them. As of 0.7, it uses: + * + * Key Value + * --- ----- + * GROWL_APP_NAME CFBundleExecutableName + * GROWL_APP_ICON The icon of the application. + * GROWL_APP_LOCATION The location of the application. + * GROWL_NOTIFICATIONS_DEFAULT GROWL_NOTIFICATIONS_ALL + * + * Only those keys that are listed in keys will be filled in. + * Other missing keys are ignored. Also, keys are only filled in if missing; + * if a key is present in the dictionary, its value will not be changed. + * + * This function was introduced in Growl.framework 0.7. + */ +CFDictionaryRef Growl_CreateRegistrationDictionaryByFillingInDictionaryRestrictedToKeys(CFDictionaryRef regDict, CFSetRef keys); + +#pragma mark - + +// @functiongroup Querying Growl's status + +/*! @function Growl_IsInstalled + * @abstract Determines whether the Growl prefpane and its helper app are + * installed. + * @result Returns true if Growl is installed, false otherwise. + */ +Boolean Growl_IsInstalled(void); + +/*! @function Growl_IsRunning + * @abstract Cycles through the process list to find whether GrowlHelperApp + * is running. + * @result Returns true if Growl is running, false otherwise. + */ +Boolean Growl_IsRunning(void); + +#pragma mark - + +// @functiongroup Launching Growl + +/*! @typedef GrowlLaunchCallback + * @abstract Callback to notify you that Growl is running. + * @param context The context pointer passed to Growl_LaunchIfInstalled. + * @discussion Growl_LaunchIfInstalled calls this callback function if Growl + * was already running or if it launched Growl successfully. + */ +typedef void (*GrowlLaunchCallback)(void *context); + +/*! @function Growl_LaunchIfInstalled + * @abstract Launches GrowlHelperApp if it is not already running. + * @param callback A callback function which will be called if Growl was successfully + * launched or was already running. Can be NULL. + * @param context The context pointer to pass to the callback. Can be NULL. + * @result Returns true if Growl was successfully launched or was already + * running; returns false and does not call the callback otherwise. + * @discussion Returns true and calls the callback (if the callback is not + * NULL) if the Growl helper app began launching or was already + * running. Returns false and performs no other action if Growl could not be + * launched (e.g. because the Growl preference pane is not properly installed). + * + * If Growl_CreateBestRegistrationDictionary returns + * non-NULL, this function will register with Growl atomically. + * + * The callback should take a single argument; this is to allow applications + * to have context-relevant information passed back. It is perfectly + * acceptable for context to be NULL. The callback itself can be + * NULL if you don't want one. + */ +Boolean Growl_LaunchIfInstalled(GrowlLaunchCallback callback, void *context); + +#pragma mark - +#pragma mark Constants + +/*! @defined GROWL_PREFPANE_BUNDLE_IDENTIFIER + * @abstract The CFBundleIdentifier of the Growl preference pane bundle. + * @discussion GrowlApplicationBridge uses this to determine whether Growl is + * currently installed, by searching for the Growl preference pane. Your + * application probably does not need to use this macro itself. + */ +#ifndef GROWL_PREFPANE_BUNDLE_IDENTIFIER +#define GROWL_PREFPANE_BUNDLE_IDENTIFIER CFSTR("com.growl.prefpanel") +#endif + +__END_DECLS + +#endif /* _GROWLAPPLICATIONBRIDGE_CARBON_H_ */ diff --git a/macosx/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h b/macosx/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h new file mode 100644 index 000000000..7ac315af3 --- /dev/null +++ b/macosx/Growl.framework/Versions/A/Headers/GrowlApplicationBridge.h @@ -0,0 +1,556 @@ +// +// GrowlApplicationBridge.h +// Growl +// +// Created by Evan Schoenberg on Wed Jun 16 2004. +// Copyright 2004-2005 The Growl Project. All rights reserved. +// + +/*! + * @header GrowlApplicationBridge.h + * @abstract Defines the GrowlApplicationBridge class. + * @discussion This header defines the GrowlApplicationBridge class as well as + * the GROWL_PREFPANE_BUNDLE_IDENTIFIER constant. + */ + +#ifndef __GrowlApplicationBridge_h__ +#define __GrowlApplicationBridge_h__ + +#import +#import "GrowlDefines.h" + +//Forward declarations +@protocol GrowlApplicationBridgeDelegate; + +/*! + * @defined GROWL_PREFPANE_BUNDLE_IDENTIFIER + * @discussion The bundle identifier for the Growl prefpane. + */ +#define GROWL_PREFPANE_BUNDLE_IDENTIFIER @"com.growl.prefpanel" + +/*! + * @defined GROWL_PREFPANE_NAME + * @discussion The file name of the Growl prefpane. + */ +#define GROWL_PREFPANE_NAME @"Growl.prefPane" + +//Internal notification when the user chooses not to install (to avoid continuing to cache notifications awaiting installation) +#define GROWL_USER_CHOSE_NOT_TO_INSTALL_NOTIFICATION @"User chose not to install" + +//------------------------------------------------------------------------------ +#pragma mark - + +/*! + * @class GrowlApplicationBridge + * @abstract A class used to interface with Growl. + * @discussion This class provides a means to interface with Growl. + * + * Currently it provides a way to detect if Growl is installed and launch the + * GrowlHelperApp if it's not already running. + */ +@interface GrowlApplicationBridge : NSObject { + +} + +/*! + * @method isGrowlInstalled + * @abstract Detects whether Growl is installed. + * @discussion Determines if the Growl prefpane and its helper app are installed. + * @result Returns YES if Growl is installed, NO otherwise. + */ ++ (BOOL) isGrowlInstalled; + +/*! + * @method isGrowlRunning + * @abstract Detects whether GrowlHelperApp is currently running. + * @discussion Cycles through the process list to find whether GrowlHelperApp is running and returns its findings. + * @result Returns YES if GrowlHelperApp is running, NO otherwise. + */ ++ (BOOL) isGrowlRunning; + +#pragma mark - + +/*! + * @method setGrowlDelegate: + * @abstract Set the object which will be responsible for providing and receiving Growl information. + * @discussion This must be called before using GrowlApplicationBridge. + * + * The methods in the GrowlApplicationBridgeDelegate protocol are required + * and return the basic information needed to register with Growl. + * + * The methods in the GrowlApplicationBridgeDelegate_InformalProtocol + * informal protocol are individually optional. They provide a greater + * degree of interaction between the application and growl such as informing + * the application when one of its Growl notifications is clicked by the user. + * + * The methods in the GrowlApplicationBridgeDelegate_Installation_InformalProtocol + * informal protocol are individually optional and are only applicable when + * using the Growl-WithInstaller.framework which allows for automated Growl + * installation. + * + * When this method is called, data will be collected from inDelegate, Growl + * will be launched if it is not already running, and the application will be + * registered with Growl. + * + * If using the Growl-WithInstaller framework, if Growl is already installed + * but this copy of the framework has an updated version of Growl, the user + * will be prompted to update automatically. + * + * @param inDelegate The delegate for the GrowlApplicationBridge. It must conform to the GrowlApplicationBridgeDelegate protocol. + */ ++ (void) setGrowlDelegate:(NSObject *)inDelegate; + +/*! + * @method growlDelegate + * @abstract Return the object responsible for providing and receiving Growl information. + * @discussion See setGrowlDelegate: for details. + * @result The Growl delegate. + */ ++ (NSObject *) growlDelegate; + +#pragma mark - + +/*! + * @method notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext: + * @abstract Send a Growl notification. + * @discussion This is the preferred means for sending a Growl notification. + * The notification name and at least one of the title and description are + * required (all three are preferred). All other parameters may be + * nil (or 0 or NO as appropriate) to accept default values. + * + * If using the Growl-WithInstaller framework, if Growl is not installed the + * user will be prompted to install Growl. If the user cancels, this method + * will have no effect until the next application session, at which time when + * it is called the user will be prompted again. The user is also given the + * option to not be prompted again. If the user does choose to install Growl, + * the requested notification will be displayed once Growl is installed and + * running. + * + * @param title The title of the notification displayed to the user. + * @param description The full description of the notification displayed to the user. + * @param notifName The internal name of the notification. Should be human-readable, as it will be displayed in the Growl preference pane. + * @param iconData NSData object to show with the notification as its icon. If nil, the application's icon will be used instead. + * @param priority The priority of the notification. The default value is 0; positive values are higher priority and negative values are lower priority. Not all Growl displays support priority. + * @param isSticky If YES, the notification will remain on screen until clicked. Not all Growl displays support sticky notifications. + * @param clickContext A context passed back to the Growl delegate if it implements -(void)growlNotificationWasClicked: and the notification is clicked. Not all display plugins support clicking. The clickContext must be plist-encodable (completely of NSString, NSArray, NSNumber, NSDictionary, and NSData types). + */ ++ (void) notifyWithTitle:(NSString *)title + description:(NSString *)description + notificationName:(NSString *)notifName + iconData:(NSData *)iconData + priority:(signed int)priority + isSticky:(BOOL)isSticky + clickContext:(id)clickContext; + +/*! + * @method notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext:identifier: + * @abstract Send a Growl notification. + * @discussion This is the preferred means for sending a Growl notification. + * The notification name and at least one of the title and description are + * required (all three are preferred). All other parameters may be + * nil (or 0 or NO as appropriate) to accept default values. + * + * If using the Growl-WithInstaller framework, if Growl is not installed the + * user will be prompted to install Growl. If the user cancels, this method + * will have no effect until the next application session, at which time when + * it is called the user will be prompted again. The user is also given the + * option to not be prompted again. If the user does choose to install Growl, + * the requested notification will be displayed once Growl is installed and + * running. + * + * @param title The title of the notification displayed to the user. + * @param description The full description of the notification displayed to the user. + * @param notifName The internal name of the notification. Should be human-readable, as it will be displayed in the Growl preference pane. + * @param iconData NSData object to show with the notification as its icon. If nil, the application's icon will be used instead. + * @param priority The priority of the notification. The default value is 0; positive values are higher priority and negative values are lower priority. Not all Growl displays support priority. + * @param isSticky If YES, the notification will remain on screen until clicked. Not all Growl displays support sticky notifications. + * @param clickContext A context passed back to the Growl delegate if it implements -(void)growlNotificationWasClicked: and the notification is clicked. Not all display plugins support clicking. The clickContext must be plist-encodable (completely of NSString, NSArray, NSNumber, NSDictionary, and NSData types). + * @param identifier An identifier for this notification. Notifications with equal identifiers are coalesced. + */ ++ (void) notifyWithTitle:(NSString *)title + description:(NSString *)description + notificationName:(NSString *)notifName + iconData:(NSData *)iconData + priority:(signed int)priority + isSticky:(BOOL)isSticky + clickContext:(id)clickContext + identifier:(NSString *)identifier; + +/*! @method notifyWithDictionary: + * @abstract Notifies using a userInfo dictionary suitable for passing to + * NSDistributedNotificationCenter. + * @param userInfo The dictionary to notify with. + * @discussion Before Growl 0.6, your application would have posted + * notifications using NSDistributedNotificationCenter by + * creating a userInfo dictionary with the notification data. This had the + * advantage of allowing you to add other data to the dictionary for programs + * besides Growl that might be listening. + * + * This method allows you to use such dictionaries without being restricted + * to using NSDistributedNotificationCenter. The keys for this dictionary + * can be found in GrowlDefines.h. + */ ++ (void) notifyWithDictionary:(NSDictionary *)userInfo; + +#pragma mark - + +/*! @method registerWithDictionary: + * @abstract Register your application with Growl without setting a delegate. + * @discussion When you call this method with a dictionary, + * GrowlApplicationBridge registers your application using that dictionary. + * If you pass nil, GrowlApplicationBridge will ask the delegate + * (if there is one) for a dictionary, and if that doesn't work, it will look + * in your application's bundle for an auto-discoverable plist. + * (XXX refer to more information on that) + * + * If you pass a dictionary to this method, it must include the + * GROWL_APP_NAME key, unless a delegate is set. + * + * This method is mainly an alternative to the delegate system introduced + * with Growl 0.6. Without a delegate, you cannot receive callbacks such as + * -growlIsReady (since they are sent to the delegate). You can, + * however, set a delegate after registering without one. + * + * This method was introduced in Growl.framework 0.7. + */ ++ (BOOL) registerWithDictionary:(NSDictionary *)regDict; + +/*! @method reregisterGrowlNotifications + * @abstract Reregister the notifications for this application. + * @discussion This method does not normally need to be called. If your + * application changes what notifications it is registering with Growl, call + * this method to have the Growl delegate's + * -registrationDictionaryForGrowl method called again and the + * Growl registration information updated. + * + * This method is now implemented using -registerWithDictionary:. + */ ++ (void) reregisterGrowlNotifications; + +#pragma mark - + +/*! @method setWillRegisterWhenGrowlIsReady: + * @abstract Tells GrowlApplicationBridge to register with Growl when Growl + * launches (or not). + * @discussion When Growl has started listening for notifications, it posts a + * GROWL_IS_READY notification on the Distributed Notification + * Center. GrowlApplicationBridge listens for this notification, using it to + * perform various tasks (such as calling your delegate's + * -growlIsReady method, if it has one). If this method is + * called with YES, one of those tasks will be to reregister + * with Growl (in the manner of -reregisterGrowlNotifications). + * + * This attribute is automatically set back to NO (the default) + * after every GROWL_IS_READY notification. + * @param flag YES if you want GrowlApplicationBridge to register with + * Growl when next it is ready; NO if not. + */ ++ (void) setWillRegisterWhenGrowlIsReady:(BOOL)flag; +/*! @method willRegisterWhenGrowlIsReady + * @abstract Reports whether GrowlApplicationBridge will register with Growl + * when Growl next launches. + * @result YES if GrowlApplicationBridge will register with Growl + * when next it posts GROWL_IS_READY; NO if not. + */ ++ (BOOL) willRegisterWhenGrowlIsReady; + +#pragma mark - + +/*! @method registrationDictionaryFromDelegate + * @abstract Asks the delegate for a registration dictionary. + * @discussion If no delegate is set, or if the delegate's + * -registrationDictionaryForGrowl method returns + * nil, this method returns nil. + * + * This method does not attempt to clean up the dictionary in any way - for + * example, if it is missing the GROWL_APP_NAME key, the result + * will be missing it too. Use +[GrowlApplicationBridge + * registrationDictionaryByFillingInDictionary:] or + * +[GrowlApplicationBridge + * registrationDictionaryByFillingInDictionary:restrictToKeys:] to try + * to fill in missing keys. + * + * This method was introduced in Growl.framework 0.7. + * @result A registration dictionary. + */ ++ (NSDictionary *) registrationDictionaryFromDelegate; + +/*! @method registrationDictionaryFromBundle: + * @abstract Looks in a bundle for a registration dictionary. + * @discussion This method looks in a bundle for an auto-discoverable + * registration dictionary file using -[NSBundle + * pathForResource:ofType:]. If it finds one, it loads the file using + * +[NSDictionary dictionaryWithContentsOfFile:] and returns the + * result. + * + * If you pass nil as the bundle, the main bundle is examined. + * + * This method does not attempt to clean up the dictionary in any way - for + * example, if it is missing the GROWL_APP_NAME key, the result + * will be missing it too. Use +[GrowlApplicationBridge + * registrationDictionaryByFillingInDictionary:] or + * +[GrowlApplicationBridge + * registrationDictionaryByFillingInDictionary:restrictToKeys:] to try + * to fill in missing keys. + * + * This method was introduced in Growl.framework 0.7. + * @result A registration dictionary. + */ ++ (NSDictionary *) registrationDictionaryFromBundle:(NSBundle *)bundle; + +/*! @method bestRegistrationDictionary + * @abstract Obtains a registration dictionary, filled out to the best of + * GrowlApplicationBridge's knowledge. + * @discussion This method creates a registration dictionary as best + * GrowlApplicationBridge knows how. + * + * First, GrowlApplicationBridge contacts the Growl delegate (if there is + * one) and gets the registration dictionary from that. If no such dictionary + * was obtained, GrowlApplicationBridge looks in your application's main + * bundle for an auto-discoverable registration dictionary file. If that + * doesn't exist either, this method returns nil. + * + * Second, GrowlApplicationBridge calls + * +registrationDictionaryByFillingInDictionary: with whatever + * dictionary was obtained. The result of that method is the result of this + * method. + * + * GrowlApplicationBridge uses this method when you call + * +setGrowlDelegate:, or when you call + * +registerWithDictionary: with nil. + * + * This method was introduced in Growl.framework 0.7. + * @result A registration dictionary. + */ ++ (NSDictionary *) bestRegistrationDictionary; + +#pragma mark - + +/*! @method registrationDictionaryByFillingInDictionary: + * @abstract Tries to fill in missing keys in a registration dictionary. + * @discussion This method examines the passed-in dictionary for missing keys, + * and tries to work out correct values for them. As of 0.7, it uses: + * + * Key Value + * --- ----- + * GROWL_APP_NAME CFBundleExecutableName + * GROWL_APP_ICON The icon of the application. + * GROWL_APP_LOCATION The location of the application. + * GROWL_NOTIFICATIONS_DEFAULT GROWL_NOTIFICATIONS_ALL + * + * Keys are only filled in if missing; if a key is present in the dictionary, + * its value will not be changed. + * + * This method was introduced in Growl.framework 0.7. + * @param regDict The dictionary to fill in. + * @result The dictionary with the keys filled in. This is an autoreleased + * copy of regDict. + */ ++ (NSDictionary *) registrationDictionaryByFillingInDictionary:(NSDictionary *)regDict; +/*! @method registrationDictionaryByFillingInDictionary:restrictToKeys: + * @abstract Tries to fill in missing keys in a registration dictionary. + * @discussion This method examines the passed-in dictionary for missing keys, + * and tries to work out correct values for them. As of 0.7, it uses: + * + * Key Value + * --- ----- + * GROWL_APP_NAME CFBundleExecutableName + * GROWL_APP_ICON The icon of the application. + * GROWL_APP_LOCATION The location of the application. + * GROWL_NOTIFICATIONS_DEFAULT GROWL_NOTIFICATIONS_ALL + * + * Only those keys that are listed in keys will be filled in. + * Other missing keys are ignored. Also, keys are only filled in if missing; + * if a key is present in the dictionary, its value will not be changed. + * + * This method was introduced in Growl.framework 0.7. + * @param regDict The dictionary to fill in. + * @param keys The keys to fill in. If nil, any missing keys are filled in. + * @result The dictionary with the keys filled in. This is an autoreleased + * copy of regDict. + */ ++ (NSDictionary *) registrationDictionaryByFillingInDictionary:(NSDictionary *)regDict restrictToKeys:(NSSet *)keys; + +@end + +//------------------------------------------------------------------------------ +#pragma mark - + +/*! + * @protocol GrowlApplicationBridgeDelegate + * @abstract Required protocol for the Growl delegate. + * @discussion The methods in this protocol are required and are called + * automatically as needed by GrowlApplicationBridge. See + * +[GrowlApplicationBridge setGrowlDelegate:]. + * See also GrowlApplicationBridgeDelegate_InformalProtocol. + */ + +@protocol GrowlApplicationBridgeDelegate + +// -registrationDictionaryForGrowl has moved to the informal protocol as of 0.7. + +@end + +//------------------------------------------------------------------------------ +#pragma mark - + +/*! + * @category NSObject(GrowlApplicationBridgeDelegate_InformalProtocol) + * @abstract Methods which may be optionally implemented by the GrowlDelegate. + * @discussion The methods in this informal protocol will only be called if implemented by the delegate. + */ +@interface NSObject (GrowlApplicationBridgeDelegate_InformalProtocol) + +/*! + * @method registrationDictionaryForGrowl + * @abstract Return the dictionary used to register this application with Growl. + * @discussion The returned dictionary gives Growl the complete list of + * notifications this application will ever send, and it also specifies which + * notifications should be enabled by default. Each is specified by an array + * of NSString objects. + * + * For most applications, these two arrays can be the same (if all sent + * notifications should be displayed by default). + * + * The NSString objects of these arrays will correspond to the + * notificationName: parameter passed in + * +[GrowlApplicationBridge + * notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext:] calls. + * + * The dictionary should have 2 key object pairs: + * key: GROWL_NOTIFICATIONS_ALL object: NSArray of NSString objects + * key: GROWL_NOTIFICATIONS_DEFAULT object: NSArray of NSString objects + * + * You do not need to implement this method if you have an auto-discoverable + * plist file in your app bundle. (XXX refer to more information on that) + * + * @result The NSDictionary to use for registration. + */ +- (NSDictionary *) registrationDictionaryForGrowl; + +/*! + * @method applicationNameForGrowl + * @abstract Return the name of this application which will be used for Growl bookkeeping. + * @discussion This name is used both internally and in the Growl preferences. + * + * This should remain stable between different versions and incarnations of + * your application. + * For example, "SurfWriter" is a good app name, whereas "SurfWriter 2.0" and + * "SurfWriter Lite" are not. + * + * You do not need to implement this method if you are providing the + * application name elsewhere, meaning in an auto-discoverable plist file in + * your app bundle (XXX refer to more information on that) or in the result + * of -registrationDictionaryForGrowl. + * + * @result The name of the application using Growl. + */ +- (NSString *) applicationNameForGrowl; + +/*! + * @method applicationIconDataForGrowl + * @abstract Return the NSData to treat as the application icon. + * @discussion The delegate may optionally return an NSData + * object to use as the application icon; if this is not implemented, the + * application's own icon is used. This is not generally needed. + * @result The NSData to treat as the application icon. + */ +- (NSData *) applicationIconDataForGrowl; + +/*! + * @method growlIsReady + * @abstract Informs the delegate that Growl has launched. + * @discussion Informs the delegate that Growl (specifically, the + * GrowlHelperApp) was launched successfully or was already running. The + * application can take actions with the knowledge that Growl is installed and + * functional. + */ +- (void) growlIsReady; + +/*! + * @method growlNotificationWasClicked: + * @abstract Informs the delegate that a Growl notification was clicked. + * @discussion Informs the delegate that a Growl notification was clicked. It + * is only sent for notifications sent with a non-nil + * clickContext, so if you want to receive a message when a notification is + * clicked, clickContext must not be nil when calling + * +[GrowlApplicationBridge notifyWithTitle: description:notificationName:iconData:priority:isSticky:clickContext:]. + * @param clickContext The clickContext passed when displaying the notification originally via +[GrowlApplicationBridge notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext:]. + */ +- (void) growlNotificationWasClicked:(id)clickContext; + +/*! + * @method growlNotificationTimedOut: + * @abstract Informs the delegate that a Growl notification timed out. + * @discussion Informs the delegate that a Growl notification timed out. It + * is only sent for notifications sent with a non-nil + * clickContext, so if you want to receive a message when a notification is + * clicked, clickContext must not be nil when calling + * +[GrowlApplicationBridge notifyWithTitle: description:notificationName:iconData:priority:isSticky:clickContext:]. + * @param clickContext The clickContext passed when displaying the notification originally via +[GrowlApplicationBridge notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext:]. + */ +- (void) growlNotificationTimedOut:(id)clickContext; + +@end + +#pragma mark - +/*! + * @category NSObject(GrowlApplicationBridgeDelegate_Installation_InformalProtocol) + * @abstract Methods which may be optionally implemented by the Growl delegate when used with Growl-WithInstaller.framework. + * @discussion The methods in this informal protocol will only be called if + * implemented by the delegate. They allow greater control of the information + * presented to the user when installing or upgrading Growl from within your + * application when using Growl-WithInstaller.framework. + */ +@interface NSObject (GrowlApplicationBridgeDelegate_Installation_InformalProtocol) + +/*! + * @method growlInstallationWindowTitle + * @abstract Return the title of the installation window. + * @discussion If not implemented, Growl will use a default, localized title. + * @result An NSString object to use as the title. + */ +- (NSString *)growlInstallationWindowTitle; + +/*! + * @method growlUpdateWindowTitle + * @abstract Return the title of the upgrade window. + * @discussion If not implemented, Growl will use a default, localized title. + * @result An NSString object to use as the title. + */ +- (NSString *)growlUpdateWindowTitle; + +/*! + * @method growlInstallationInformation + * @abstract Return the information to display when installing. + * @discussion This information may be as long or short as desired (the window + * will be sized to fit it). It will be displayed to the user as an + * explanation of what Growl is and what it can do in your application. It + * should probably note that no download is required to install. + * + * If this is not implemented, Growl will use a default, localized explanation. + * @result An NSAttributedString object to display. + */ +- (NSAttributedString *)growlInstallationInformation; + +/*! + * @method growlUpdateInformation + * @abstract Return the information to display when upgrading. + * @discussion This information may be as long or short as desired (the window + * will be sized to fit it). It will be displayed to the user as an + * explanation that an updated version of Growl is included in your + * application and no download is required. + * + * If this is not implemented, Growl will use a default, localized explanation. + * @result An NSAttributedString object to display. + */ +- (NSAttributedString *)growlUpdateInformation; + +@end + +//private +@interface GrowlApplicationBridge (GrowlInstallationPrompt_private) ++ (void) _userChoseNotToInstallGrowl; +@end + +#endif /* __GrowlApplicationBridge_h__ */ diff --git a/macosx/Growl.framework/Versions/A/Headers/GrowlDefines.h b/macosx/Growl.framework/Versions/A/Headers/GrowlDefines.h new file mode 100644 index 000000000..6ff6ee3d2 --- /dev/null +++ b/macosx/Growl.framework/Versions/A/Headers/GrowlDefines.h @@ -0,0 +1,307 @@ +// +// GrowlDefines.h +// + +#ifndef _GROWLDEFINES_H +#define _GROWLDEFINES_H + +#ifdef __OBJC__ +#define XSTR(x) (@x) +#define STRING NSString * +#else +#define XSTR CFSTR +#define STRING CFStringRef +#endif + +/*! @header GrowlDefines.h + * @abstract Defines all the notification keys. + * @discussion Defines all the keys used for registration with Growl and for + * Growl notifications. + * + * Most applications should use the functions or methods of Growl.framework + * instead of posting notifications such as those described here. + * @updated 2004-01-25 + */ + +// UserInfo Keys for Registration +#pragma mark UserInfo Keys for Registration + +/*! @group Registration userInfo keys */ +/* @abstract Keys for the userInfo dictionary of a GROWL_APP_REGISTRATION distributed notification. + * @discussion The values of these keys describe the application and the + * notifications it may post. + * + * Your application must register with Growl before it can post Growl + * notifications (and have them not be ignored). However, as of Growl 0.6, + * posting GROWL_APP_REGISTRATION notifications directly is no longer the + * preferred way to register your application. Your application should instead + * use Growl.framework's delegate system. + * See +[GrowlApplicationBridge setGrowlDelegate:] or Growl_SetDelegate for + * more information. + */ + +/*! @defined GROWL_APP_NAME + * @abstract The name of your application. + * @discussion The name of your application. This should remain stable between + * different versions and incarnations of your application. + * For example, "SurfWriter" is a good app name, whereas "SurfWriter 2.0" and + * "SurfWriter Lite" are not. + */ +#define GROWL_APP_NAME XSTR("ApplicationName") +/*! @defined GROWL_APP_ICON + * @abstract The image data for your application's icon. + * @discussion Image data representing your application's icon. This may be + * superimposed on a notification icon as a badge, used as the notification + * icon when a notification-specific icon is not supplied, or ignored + * altogether, depending on the display. Must be in a format supported by + * NSImage, such as TIFF, PNG, GIF, JPEG, BMP, PICT, or PDF. + * + * Optional. Not supported by all display plugins. + */ +#define GROWL_APP_ICON XSTR("ApplicationIcon") +/*! @defined GROWL_NOTIFICATIONS_DEFAULT + * @abstract The array of notifications to turn on by default. + * @discussion These are the names of the notifications that should be enabled + * by default when your application registers for the first time. If your + * application reregisters, Growl will look here for any new notification + * names found in GROWL_NOTIFICATIONS_ALL, but ignore any others. + */ +#define GROWL_NOTIFICATIONS_DEFAULT XSTR("DefaultNotifications") +/*! @defined GROWL_NOTIFICATIONS_ALL + * @abstract The array of all notifications your application can send. + * @discussion These are the names of all of the notifications that your + * application may post. See GROWL_NOTIFICATION_NAME for a discussion of good + * notification names. + */ +#define GROWL_NOTIFICATIONS_ALL XSTR("AllNotifications") +/*! @defined GROWL_TICKET_VERSION + * @abstract The version of your registration ticket. + * @discussion Include this key in a ticket plist file that you put in your + * application bundle for auto-discovery. The current ticket version is 1. + */ +#define GROWL_TICKET_VERSION XSTR("TicketVersion") +// UserInfo Keys for Notifications +#pragma mark UserInfo Keys for Notifications + +/*! @group Notification userInfo keys */ +/* @abstract Keys for the userInfo dictionary of a GROWL_NOTIFICATION distributed notification. + * @discussion The values of these keys describe the content of a Growl + * notification. + * + * Not all of these keys are supported by all displays. Only the name, title, + * and description of a notification are universal. Most of the built-in + * displays do support all of these keys, and most other visual displays + * probably will also. But, as of 0.6, the Log, MailMe, and Speech displays + * support only textual data. + */ + +/*! @defined GROWL_NOTIFICATION_NAME + * @abstract The name of the notification. + * @discussion The name of the notification. This should be human-readable, as + * it's shown in the prefpane, in the list of notifications your application + * supports. */ +#define GROWL_NOTIFICATION_NAME XSTR("NotificationName") +/*! @defined GROWL_NOTIFICATION_TITLE + * @abstract The title to display in the notification. + * @discussion The title of the notification. Should be very brief. + * The title usually says what happened, e.g. "Download complete". + */ +#define GROWL_NOTIFICATION_TITLE XSTR("NotificationTitle") +/*! @defined GROWL_NOTIFICATION_DESCRIPTION + * @abstract The description to display in the notification. + * @discussion The description should be longer and more verbose than the title. + * The description usually tells the subject of the action, + * e.g. "Growl-0.6.dmg downloaded in 5.02 minutes". + */ +#define GROWL_NOTIFICATION_DESCRIPTION XSTR("NotificationDescription") +/*! @defined GROWL_NOTIFICATION_ICON + * @discussion Image data for the notification icon. Must be in a format + * supported by NSImage, such as TIFF, PNG, GIF, JPEG, BMP, PICT, or PDF. + * + * Optional. Not supported by all display plugins. + */ +#define GROWL_NOTIFICATION_ICON XSTR("NotificationIcon") +/*! @defined GROWL_NOTIFICATION_APP_ICON + * @discussion Image data for the application icon, in case GROWL_APP_ICON does + * not apply for some reason. Must be in a format supported by NSImage, such + * as TIFF, PNG, GIF, JPEG, BMP, PICT, or PDF. + * + * Optional. Not supported by all display plugins. + */ +#define GROWL_NOTIFICATION_APP_ICON XSTR("NotificationAppIcon") +/*! @defined GROWL_NOTIFICATION_PRIORITY + * @discussion The priority of the notification as an integer number from + * -2 to +2 (+2 being highest). + * + * Optional. Not supported by all display plugins. + */ +#define GROWL_NOTIFICATION_PRIORITY XSTR("NotificationPriority") +/*! @defined GROWL_NOTIFICATION_STICKY + * @discussion A Boolean number controlling whether the notification is sticky. + * + * Optional. Not supported by all display plugins. + */ +#define GROWL_NOTIFICATION_STICKY XSTR("NotificationSticky") +/*! @defined GROWL_NOTIFICATION_CLICK_CONTEXT + * @abstract Identifies which notification was clicked. + * @discussion An identifier for the notification for clicking purposes. + * + * This will be passed back to the application when the notification is + * clicked. It must be plist-encodable (a data, dictionary, array, number, or + * string object), and it should be unique for each notification you post. + * A good click context would be a UUID string returned by NSProcessInfo or + * CFUUID. + * + * Optional. Not supported by all display plugins. + */ +#define GROWL_NOTIFICATION_CLICK_CONTEXT XSTR("NotificationClickContext") + +/*! @defined GROWL_DISPLAY_PLUGIN + * @discussion The name of a display plugin which should be used for this notification. + * Optional. If this key is not set or the specified display plugin does not + * exist, the display plugin stored in the application ticket is used. This key + * allows applications to use different default display plugins for their + * notifications. The user can still override those settings in the preference + * pane. + */ +#define GROWL_DISPLAY_PLUGIN XSTR("NotificationDisplayPlugin") + +/*! @defined GROWL_NOTIFICATION_IDENTIFIER + * @abstract An identifier for the notification for coalescing purposes. + * Notifications with the same identifier fall into the same class; only + * the last notification of a class is displayed on the screen. If a + * notification of the same class is currently being displayed, it is + * replaced by this notification. + * + * Optional. Not supported by all display plugins. + */ +#define GROWL_NOTIFICATION_IDENTIFIER XSTR("GrowlNotificationIdentifier") + +/*! @defined GROWL_APP_PID + * @abstract The process identifier of the process which sends this + * notification. If this field is set, the application will only receive + * clicked and timed out notifications which originate from this process. + * + * Optional. + */ +#define GROWL_APP_PID XSTR("ApplicationPID") + +// Notifications +#pragma mark Notifications + +/*! @group Notification names */ +/* @abstract Names of distributed notifications used by Growl. + * @discussion These are notifications used by applications (directly or + * indirectly) to interact with Growl, and by Growl for interaction between + * its components. + * + * Most of these should no longer be used in Growl 0.6 and later, in favor of + * Growl.framework's GrowlApplicationBridge APIs. + */ + +/*! @defined GROWL_APP_REGISTRATION + * @abstract The distributed notification for registering your application. + * @discussion This is the name of the distributed notification that can be + * used to register applications with Growl. + * + * The userInfo dictionary for this notification can contain these keys: + *
    + *
  • GROWL_APP_NAME
  • + *
  • GROWL_APP_ICON
  • + *
  • GROWL_NOTIFICATIONS_ALL
  • + *
  • GROWL_NOTIFICATIONS_DEFAULT
  • + *
+ * + * No longer recommended as of Growl 0.6. An alternate method of registering + * is to use Growl.framework's delegate system. + * See +[GrowlApplicationBridge setGrowlDelegate:] or Growl_SetDelegate for + * more information. + */ +#define GROWL_APP_REGISTRATION XSTR("GrowlApplicationRegistrationNotification") +/*! @defined GROWL_APP_REGISTRATION_CONF + * @abstract The distributed notification for confirming registration. + * @discussion The name of the distributed notification sent to confirm the + * registration. Used by the Growl preference pane. Your application probably + * does not need to use this notification. + */ +#define GROWL_APP_REGISTRATION_CONF XSTR("GrowlApplicationRegistrationConfirmationNotification") +/*! @defined GROWL_NOTIFICATION + * @abstract The distributed notification for Growl notifications. + * @discussion This is what it all comes down to. This is the name of the + * distributed notification that your application posts to actually send a + * Growl notification. + * + * The userInfo dictionary for this notification can contain these keys: + *
    + *
  • GROWL_NOTIFICATION_NAME (required)
  • + *
  • GROWL_NOTIFICATION_TITLE (required)
  • + *
  • GROWL_NOTIFICATION_DESCRIPTION (required)
  • + *
  • GROWL_NOTIFICATION_ICON
  • + *
  • GROWL_NOTIFICATION_APP_ICON
  • + *
  • GROWL_NOTIFICATION_PRIORITY
  • + *
  • GROWL_NOTIFICATION_STICKY
  • + *
  • GROWL_NOTIFICATION_CLICK_CONTEXT
  • + *
  • GROWL_APP_NAME (required)
  • + *
+ * + * No longer recommended as of Growl 0.6. Three alternate methods of posting + * notifications are +[GrowlApplicationBridge notifyWithTitle:description:notificationName:iconData:priority:isSticky:clickContext:], + * Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext, and + * Growl_PostNotification. + */ +#define GROWL_NOTIFICATION XSTR("GrowlNotification") +/*! @defined GROWL_SHUTDOWN +* @abstract The distributed notification name that tells Growl to shutdown. +* @discussion The Growl preference pane posts this notification when the +* "Stop Growl" button is clicked. +*/ +#define GROWL_SHUTDOWN XSTR("GrowlShutdown") +/*! @defined GROWL_PING + * @abstract A distributed notification to check whether Growl is running. + * @discussion This is used by the Growl preference pane. If it receives a + * GROWL_PONG, the preference pane takes this to mean that Growl is running. + */ +#define GROWL_PING XSTR("Honey, Mind Taking Out The Trash") +/*! @defined GROWL_PONG + * @abstract The distributed notification sent in reply to GROWL_PING. + * @discussion GrowlHelperApp posts this in reply to GROWL_PING. + */ +#define GROWL_PONG XSTR("What Do You Want From Me, Woman") +/*! @defined GROWL_IS_READY + * @abstract The distributed notification sent when Growl starts up. + * @discussion GrowlHelperApp posts this when it has begin listening on all of + * its sources for new notifications. GrowlApplicationBridge (in + * Growl.framework), upon receiving this notification, reregisters using the + * registration dictionary supplied by its delegate. + */ +#define GROWL_IS_READY XSTR("Lend Me Some Sugar; I Am Your Neighbor!") +/*! @defined GROWL_NOTIFICATION_CLICKED + * @abstract The distributed notification sent when a supported notification is clicked. + * @discussion When a Growl notification with a click context is clicked on by + * the user, Growl posts this distributed notification. + * The GrowlApplicationBridge responds to this notification by calling a + * callback in its delegate. + */ +#define GROWL_NOTIFICATION_CLICKED XSTR("GrowlClicked!") +#define GROWL_NOTIFICATION_TIMED_OUT XSTR("GrowlTimedOut!") + +/*! @group Other symbols */ +/* Symbols which don't fit into any of the other categories. */ + +/*! @defined GROWL_KEY_CLICKED_CONTEXT + * @abstract Used internally as the key for the clickedContext passed over DNC. + * @discussion This key is used in GROWL_NOTIFICATION_CLICKED, and contains the + * click context that was supplied in the original notification. + */ +#define GROWL_KEY_CLICKED_CONTEXT XSTR("ClickedContext") +/*! @defined GROWL_REG_DICT_EXTENSION + * @abstract The filename extension for registration dictionaries. + * @discussion The GrowlApplicationBridge in Growl.framework registers with + * Growl by creating a file with the extension of .(GROWL_REG_DICT_EXTENSION) + * and opening it in the GrowlHelperApp. This happens whether or not Growl is + * running; if it was stopped, it quits immediately without listening for + * notifications. + */ +#define GROWL_REG_DICT_EXTENSION XSTR("growlRegDict") + +#endif //ndef _GROWLDEFINES_H diff --git a/macosx/Growl.framework/Versions/A/Resources/Info.plist b/macosx/Growl.framework/Versions/A/Resources/Info.plist new file mode 100644 index 000000000..6530bd21e --- /dev/null +++ b/macosx/Growl.framework/Versions/A/Resources/Info.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + Growl + CFBundleIdentifier + com.growl.growlframework + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + FMWK + CFBundleShortVersionString + 0.7.6 + CFBundleSignature + GRRR + CFBundleVersion + 0.7.6 + NSPrincipalClass + GrowlApplicationBridge + + diff --git a/macosx/Growl.framework/Versions/Current b/macosx/Growl.framework/Versions/Current new file mode 120000 index 000000000..8c7e5a667 --- /dev/null +++ b/macosx/Growl.framework/Versions/Current @@ -0,0 +1 @@ +A \ No newline at end of file diff --git a/macosx/HandBrake.xcodeproj/project.pbxproj b/macosx/HandBrake.xcodeproj/project.pbxproj index 0c099ba7a..4e3f229c9 100644 --- a/macosx/HandBrake.xcodeproj/project.pbxproj +++ b/macosx/HandBrake.xcodeproj/project.pbxproj @@ -104,6 +104,8 @@ 593034EC0BBA39A100172349 /* ChapterTitles.m in Sources */ = {isa = PBXBuildFile; fileRef = 593034EA0BBA39A100172349 /* ChapterTitles.m */; }; 59CBD2370BBB44DA004A3BE3 /* parsecsv.c in Sources */ = {isa = PBXBuildFile; fileRef = 59CBD2360BBB44DA004A3BE3 /* parsecsv.c */; }; 59CBD2650BBB4D1B004A3BE3 /* ChapterTitles.m in Sources */ = {isa = PBXBuildFile; fileRef = 593034EA0BBA39A100172349 /* ChapterTitles.m */; }; + A29E05800BE1283E000533F5 /* Growl.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = A29E057F0BE1283E000533F5 /* Growl.framework */; }; + A29E058B0BE12889000533F5 /* Growl.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = A29E057F0BE1283E000533F5 /* Growl.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -130,6 +132,19 @@ }; /* End PBXContainerItemProxy section */ +/* Begin PBXCopyFilesBuildPhase section */ + A29E05840BE12861000533F5 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + A29E058B0BE12889000533F5 /* Growl.framework in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + /* Begin PBXFileReference section */ 089C165DFE840E0CC02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = ""; }; 0D096DFF0B707D1200A845D4 /* libhb.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libhb.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -200,6 +215,7 @@ 593034E90BBA39A100172349 /* ChapterTitles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ChapterTitles.h; sourceTree = ""; }; 593034EA0BBA39A100172349 /* ChapterTitles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ChapterTitles.m; sourceTree = ""; }; 59CBD2360BBB44DA004A3BE3 /* parsecsv.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = parsecsv.c; path = ../test/parsecsv.c; sourceTree = SOURCE_ROOT; }; + A29E057F0BE1283E000533F5 /* Growl.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Growl.framework; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -243,6 +259,7 @@ 4DD93FA3082036E8008E1322 /* IOKit.framework in Frameworks */, 4DD93FA4082036E8008E1322 /* OpenGL.framework in Frameworks */, 4D1125D809D72FD200E0657B /* libz.dylib in Frameworks */, + A29E05800BE1283E000533F5 /* Growl.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -298,6 +315,7 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( + A29E057F0BE1283E000533F5 /* Growl.framework */, 4D1125D709D72FD200E0657B /* libz.dylib */, 1058C7A1FEA54F0111CA2CBB /* Cocoa.framework */, 4DEB2024052B055F00C39CA9 /* IOKit.framework */, @@ -501,6 +519,7 @@ 4DD93F95082036E8008E1322 /* Resources */, 4DD93F99082036E8008E1322 /* Sources */, 4DD93FA1082036E8008E1322 /* Frameworks */, + A29E05840BE12861000533F5 /* CopyFiles */, ); buildRules = ( ); @@ -959,7 +978,11 @@ buildSettings = { CONFIGURATION_BUILD_DIR = ..; CURRENT_PROJECT_VERSION = 0.8.5b1; - FRAMEWORK_SEARCH_PATHS = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)\""; GCC_OPTIMIZATION_LEVEL = s; GCC_TREAT_WARNINGS_AS_ERRORS = NO; HEADER_SEARCH_PATHS = ( @@ -1439,7 +1462,11 @@ CONFIGURATION_BUILD_DIR = ..; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 0.8.5b1; - FRAMEWORK_SEARCH_PATHS = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)\""; GCC_DYNAMIC_NO_PIC = YES; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_GENERATE_DEBUGGING_SYMBOLS = YES; @@ -1489,7 +1516,11 @@ CONFIGURATION_BUILD_DIR = ..; COPY_PHASE_STRIP = YES; CURRENT_PROJECT_VERSION = 0.8.5b1; - FRAMEWORK_SEARCH_PATHS = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)\""; GCC_ENABLE_FIX_AND_CONTINUE = NO; GCC_OPTIMIZATION_LEVEL = s; GCC_TREAT_WARNINGS_AS_ERRORS = NO; @@ -1536,7 +1567,11 @@ buildSettings = { CONFIGURATION_BUILD_DIR = ..; CURRENT_PROJECT_VERSION = 0.8.5b1; - FRAMEWORK_SEARCH_PATHS = ""; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(FRAMEWORK_SEARCH_PATHS_QUOTED_1)", + ); + FRAMEWORK_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)\""; GCC_OPTIMIZATION_LEVEL = s; GCC_TREAT_WARNINGS_AS_ERRORS = NO; HEADER_SEARCH_PATHS = ( -- 2.40.0