Posting notification to Growl without an application bundle

6 views
Skip to first unread message

jjgod

unread,
Jan 3, 2008, 3:48:18 PM1/3/08
to Growl Discuss
Is that possible? I tried the following code, it runs without an error
or warning, but
no message is showed.

#include <Growl/Growl.h>

void growl_notify_mail(const char *intro, const char *from, const char
*subj)
{
struct Growl_Delegate *delegate;
CFStringRef notificationName = CFSTR("Mail Received");
delegate = Growl_GetDelegate();
CFDictionaryRef dict;

CFStringRef notifications[] = { notificationName };
CFArrayRef allNotifications = CFArrayCreate(NULL,
(const void **)
notifications,

sizeof(notifications) / sizeof(notifications[0]),

&kCFTypeArrayCallBacks);
CFArrayRef defaultNotifications = CFArrayCreateCopy(NULL,
allNotifications);

CFTypeRef keys[] = { GROWL_NOTIFICATIONS_ALL,
GROWL_NOTIFICATIONS_DEFAULT,
GROWL_APP_ID,
GROWL_APP_NAME };
CFTypeRef values[] = { allNotifications, defaultNotifications,
CFSTR("org.jjgod.test"), CFSTR("test") };

dict = CFDictionaryCreate(NULL,
keys, values,
sizeof(keys) / sizeof(keys[0]),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);

Growl_RegisterWithDictionary(dict);

CFStringRef appName = CFSTR("alpine");
CFStringRef title = CFStringCreateWithCString(NULL, "Hello",

kCFStringEncodingUTF8);
CFStringRef description = CFStringCreateWithCString(NULL, "Mail
Received.",

kCFStringEncodingUTF8);
CFTypeRef notiKeys[] = {
GROWL_APP_NAME,
GROWL_APP_PID,
GROWL_NOTIFICATION_NAME,
GROWL_NOTIFICATION_TITLE,
GROWL_NOTIFICATION_DESCRIPTION,
GROWL_NOTIFICATION_PRIORITY,
GROWL_NOTIFICATION_STICKY,
};

int pid = getpid();
int priority = 0;
CFNumberRef pidNumber = CFNumberCreate(kCFAllocatorDefault,
kCFNumberIntType, &pid);
CFNumberRef priorityNumber = CFNumberCreate(kCFAllocatorDefault,
kCFNumberIntType,
&(priority));
Boolean isSticky = false;
CFNumberRef stickyNumber = CFNumberCreate(kCFAllocatorDefault,
kCFNumberCharType, &isSticky);
CFTypeRef notiValues[] = {
appName,
pidNumber,
notificationName,
title,
description,
priorityNumber,
stickyNumber,
};

CFDictionaryRef notiDict = CFDictionaryCreate(NULL,
notiKeys,
notiValues,
7,

&kCFTypeDictionaryKeyCallBacks,

&kCFTypeDictionaryValueCallBacks);

Growl_PostNotificationWithDictionary(notiDict);

CFRelease(title);
CFRelease(description);
}

int main(int argc, char *argv[])
{
growl_notify_mail("Mail...", "Jjgod", "Blahblah");
return 0;
}

- Jiang

Peter Hosey

unread,
Jan 3, 2008, 4:30:01 PM1/3/08
to growld...@googlegroups.com
On Jan 03, 2008, at 12:48:18, jjgod wrote:
> Is that possible?

Yes. Witness growlnotify.

> I tried the following code, it runs without an error or warning,
> but no message is showed.

That's because you did not create and set a delegate.

By the way, you also leak most of your CF objects here.

PGP.sig

jjgod

unread,
Jan 3, 2008, 5:36:55 PM1/3/08
to Growl Discuss
Hi,

On 1月4日, 上午5时30分, Peter Hosey <bore...@gmail.com> wrote:
> On Jan 03, 2008, at 12:48:18, jjgod wrote:
>
> > Is that possible?
>
> Yes. Witness growlnotify.

I wish I could, but the website is currently down..

> That's because you did not create and set a delegate.
>
> By the way, you also leak most of your CF objects here.

Sorry I didn't mention that at first I did create a delegate, use
the traditional
Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext,
but still no luck. See the following sample (leaks are fixed, too):

#include <Growl/Growl.h>

int main(int argc, char *argv[])
{
struct Growl_Delegate *delegate;
CFStringRef notificationName = CFSTR("Mail Received");

delegate = (struct Growl_Delegate *) malloc(sizeof(struct
Growl_Delegate));
InitGrowlDelegate(delegate);

delegate->applicationName = CFSTR("test");

CFStringRef notifications[] = { notificationName };
CFArrayRef allNotifications = CFArrayCreate(NULL,
(const void **)
notifications,

sizeof(notifications) / sizeof(notifications[0]),

&kCFTypeArrayCallBacks);
CFTypeRef keys[] = { GROWL_NOTIFICATIONS_ALL,
GROWL_APP_ID };
CFTypeRef values[] = { allNotifications,
CFSTR("org.jjgod.test") };

CFDictionaryRef dict = CFDictionaryCreate(NULL,
keys, values,
sizeof(keys) /
sizeof(keys[0]),

&kCFTypeDictionaryKeyCallBacks,

&kCFTypeDictionaryValueCallBacks);
delegate->registrationDictionary = dict;
Growl_SetDelegate(delegate);

CFRelease(allNotifications);


Growl_NotifyWithTitleDescriptionNameIconPriorityStickyClickContext(
CFSTR("hello"),
CFSTR("world"),
notificationName,
NULL, 0, false, NULL);

free(delegate);

return 0;
}

BTW: If a delegate is not present, there must be some warning like:

GrowlApplicationBridge: Growl_PostNotification called, but no delegate
is in effect to supply an
application name - either set a delegate, or use
Growl_PostNotificationWithDictionary instead

If I understood it correctly.

- Jiang

Jjgod Jiang

unread,
Jan 3, 2008, 5:42:53 PM1/3/08
to bor...@gmail.com, growld...@googlegroups.com
Oops, it seems my last mail is wrapped by the web interface of gmail.

Peter Hosey

unread,
Jan 3, 2008, 11:49:04 PM1/3/08
to growld...@googlegroups.com
On Jan 03, 2008, at 14:42:53, Jjgod Jiang wrote:
> On 1月4日, 上午5时30分, Peter Hosey <bore...@gmail.com> wrote:
>> Yes. Witness growlnotify.
>
> I wish I could, but the website is currently down..

You don't need the website. growlnotify is on the same disk image
with Growl, in the Extras folder.

> [the code]

Well, first off, I recommend releasing allNotifications immediately
after calling CFDictionaryCreate. Your current location of that
CFRelease confused me a little. It may just be me, though.

As far as posting a notification: It works for me.

> BTW: If a delegate is not present, there must be some warning like:
>
> GrowlApplicationBridge: Growl_PostNotification called, but no
> delegate is in effect to supply an application name - either set a
> delegate, or use Growl_PostNotificationWithDictionary instead

Or, how about:

Delegate did not supply a registration dictionary, and the app
bundle at %@ does not have one

That's what the existing warning says.

Jjgod Jiang

unread,
Jan 4, 2008, 2:55:32 AM1/4/08
to growld...@googlegroups.com
Hi Peter,

On Thu, 3 Jan 2008, Peter Hosey wrote:
> You don't need the website. growlnotify is on the same disk image
> with Growl, in the Extras folder.

I see.

> Well, first off, I recommend releasing allNotifications immediately
> after calling CFDictionaryCreate. Your current location of that
> CFRelease confused me a little. It may just be me, though.

Agreed.

> As far as posting a notification: It works for me.

It's weird, when I tried several times before, Growl *is* running but no
notifications showed, just after I restarted Growl, it works. Anyway,
thanks for you clarification, though I'm still not sure why it acted like
this.

- Jiang

Reply all
Reply to author
Forward
0 new messages