Developers‎ > ‎

Developer Guide

Introduction

Welcome!  This guide will tell you all you need to know about integrating support for Snarl into your application, and more besides.

There are two ways to talk to Snarl:
  • Natively, via the API itself
  • Via a library or header file
Talking to Snarl natively is pretty straightforward, but you have to do a bit of extra work, and you really need to understand the request structure and Snarl's concept of transports.  The best way, therefore, is to use a library or header file.

The recommended approach is to use the Snarl Framework as this:
  • is an ActiveX/COM object and thus is accessible from many languages;
  • has no other library dependencies (so it even works on NT4.0 and Windows 98 for example);
  • supports sending notifications to the local or a remote computer seamlessly;
  • handles callback events from Snarl and passes them to your application;
  • provides a built-in notification that is displayed if Snarl isn't installed or running on the computer.
Alternatively, any of the following can be used, especially if you'd rather integrate Snarl support directly into your application and not rely on middleware:

Language  Library 
Header file coming soon 
C# (or any .net-compatible language) SnarlInterface by Toke 
A modified version of SnarlInterface which uses the Snarl Framework by Pako
C++  SnarlInterface by Toke 
Delphi  Header by full phat products 
Java  SnarlNetworkBridge - by Patrick von Reth 
Python  pySnarl by Pako
PySNP by Shawn McTear 
Ruby  ruby-snarl by Patrick Hurley
VB6  Module by full phat products 
Windows Command Line Interface  HeySnarl by full phat products 

As well as the above, Snarl also supports:

V44 Changes

As of V44 (Release 3.0), the way notifications are interacted with by the user has changed.  While completely transparent to applications, the changes - and the reasoning behind the changes - are documented here.

Integrating Snarl

Applications talk to Snarl by sending a request.  A request is simply a command with zero or more arguments separated by ampersands, and each argument consists of a variable name and value separated by an equals sign.  If a command has arguments, the first argument is separated from the command by a question mark, as follows:

<command>[[?<param>=<value>][&<param>=<value>]]...

How the request is actually sent to Snarl depends on the transport that is used.  Briefly, a transport is a low-level mechanism that handles the communication between your application and Snarl itself.  Transports are described in more detail in the API Reference; however, unless you're wanting to access the API directly, you typically won't need to worry about this as the library or header you use will handle it.

Each request returns a result which indicates whether it was successful or not.  Usually, a return value of zero indicates success and a non-zero value indicates an error of some sort (see the Status Codes section for more information on error values).  How the result is returned to your application depends on the library or header file you're using, so check the documentation for it for more information.

The rest of this guide explains how applications should best work with Snarl.  Where examples are provided, they usually use the API format in order to remain language-agnostic.  Again, check the documentation for the library you're using for information specific to it.

It's not just terminology: Requests are just that - a request for Snarl to do something on your application's behalf.  Ultimately, the end user has power of veto over any notifications you may generate, so Snarl may or may not be able to honour your request, or it may be deferred for processing at a later time.  Consequently, you should always check the result of any request you send to Snarl, and you should consider alternative means for alerting your users if you absolutely need to ensure they don't miss something important.

Registering

The first thing your application should do is register with Snarl.  It can do this at any time, although it must register before attempting to send any notifications.  The most common method is to register as part of the application's initialisation process, however it is recommended that the application registers each time it generates a notification - this avoids issues which can occur if Snarl is unloaded and then reloaded after the application has registered.

Applications register with Snarl using the register command, for example:

register?app-sig=application/x-vnd-acme.some_app&title=Test Application

Applications must provide at least a valid signature and title in order to successfully register with Snarl.  The signature is used to uniquely identify the application and the title identifies the application to the user.

In order to ensure your application's signature is unique, the recommendation is to follow the Internet Media type (also known as MIME content type) format as defined in IETF RFC 2046 which contains the application vendor's name - specifically: application/x-vnd-some_vendor.some_app.  The signature must not contain spaces.  Some examples of acceptable signatures:

application/x-vnd-acme.hello_world
application/x-vnd-fullphat.snaRSS

Applications should also provide an icon which helps identify it to the user, the icon can be an image file stored on the computer or remote filesystem, a URL to an icon, a handle to a Windows icon, an icon in a resource file, or a stock icon provided with Snarl.  If an icon isn't provided, Snarl will try to use the application's own icon.  For more information, see Icons below.

Events (Notification Classes)

Events allow the user to selectively configure the different types of notifications your application generates.  While it's feasible to have no events, this limits the end user to an all-or-nothing approach when it comes to determining which notifications they wish to receive, leading to a poor user experience.

To add an event, use the addclass command.  Note that while the settings for each event persist after your application has quit, the events themselves do not, so your application must add its events each time it registers.

Name, description

Enabled by default

Defaults - title, text, sound, icon

To remove a notification class use remclass.  Removing classes is only necessary if you wish to dynamically change the classes your application is providing while the application is running.

Notifications

Creating a Notification

An application creates a notification using the notify command.  This command accepts a large number of arguments, however most are optional.  Firstly, the application must supply it's signature (and password if one was used during registration) and the name of the notification class to use to display it.  It must also supply at least one of a title, body text or an icon.

app-sig={application_signature}&title={notification_title}&text={body_text}

The following pseudo-code creates a simple notification:

// assume application registered as "application/acme-test"
sendrequest("notify?app-sig=application/acme-test&title=A notification&text=Hello, world!")

Providing an Icon

All notifications should include an icon.  In fact, it may be sufficient to simply provide an icon with no title or body text in order to get the intention of the notification across (for example, the "Volume muted" notification generated by AudioMon).  An icon can be provided in two ways: either indirectly by referencing a file or stock icon:

icon={path_to_icon|url_to_icon|!stock_icon|%HICON|path_to_resource,index}

Or by including it as byte data within the request itself:

icon-phat64={base64_encoded_bytes}

The former method is preferred as it keeps the length of the request down, and no time is spent encoding and decoding the icon data.  However, if the notification is being sent to a remote computer, and that icon will not exist on the computer (or is not accessible to it), then sending the icon as data is the only option.
 
Note that when attempting to pass an HICON (that is, a GDI handle to icon data), the HICON value must be passed as a string value prefixed with "%" - for example, "%123456".  The value should not be converted to hexadecimal, or otherwise modified.  The following pseudo-code indicates this further:
 
value_to_pass = "%" & CStr(my_returned_icon_handle)
 
If an icon isn't provided Snarl will try to use the application's own icon.  For more information, including a more detailed explanation of how icon data should be encoded, see the section on Icons below.

Playing a Sound

Snarl can play a sound when it displays the notification, as follows:

sound={!system sound|sound file}

Prefixing the sound with an exclamation mark indicates that a system sound with the supplied name should be played.

Although applications can provide their own sound for the notification to play, doing this has been deprecated as of Snarl 2.3 in favour of allowing the user to choose two sounds: one for normal priority notifications and one for high priority notifications as this helps ensure consistency across all notifications. As always, the user is able to control which sounds are played and can disable all sounds if they so wish.

Setting the Duration

The amount of time a notification should remain on-screen can be provided by the application as follows:

timeout={seconds}

There are two special values which can be used: zero, to indicate that the notification should remain on-screen until specifically dismissed by the user, and -1 (the default) to indicate that the notification should remain on-screen for the default amount of time (which is user-configurable).

Note that any value supplied should be considered as a suggested duration.  Snarl may impose restrictions on the value supplied - especially if the notification has a low priority, or will be displayed non-interactively.  Generally speaking, applications should avoid prescribing the amount of time a notification should remain on screen and leave it to Snarl and the user to decide.

Assigning a Priority

A priority is assigned using the priority argument as follows:

priority={-1|0|1}

A priority of -1 indicates the notification is of low importance and, as such, isn't detrimental to the user if they don't actually see if appear.  A priority of 1 indicates the notification is of high importance, in which case Snarl will attempt to ensure the notification is displayed to the user; a priority of zero is effectively a no-op - Snarl treats the notification as a regular notification.

With the release of Snarl 2.4, each application may only have one low priority notification may be on-screen at any one time.  When a new low priority notification appears, any existing low priority notification the application may have created is removed before the new one is displayed.  Additionally, low priority notifications are not displayed or logged as missed while the user is away or busy.

Conversely, high priority notifications are displayed even when Snarl's Do Not Disturb mode is enabled. For this reason alone they should be used very sparingly (see the Notification Guidelines section for more information).  Examples of notifications for which a high priority might be suitable include:
  • Low power warning on a battery-powered system;
  • Anti-Virus infection detection;
  • UPS power supply activating.
Of course, if the user has to leave home at 6pm to catch his or her 11pm flight, they might consider an alarm or hourly reminder suitable for high priority status. The difference here though is that this would be a user choice, not an application choice. Generally speaking, it's best to assume your notification does not need to be a high priority one and leave it to the user to decide for themselves.

Indicating a Notification's Sensitivity

With the release of Snarl 2.5.1, an application can assign a sensitivity rating to a notification.  Currently, Snarl doesn't take any specific action based on the rating assigned; instead the value is passed through to the handling style, which may then take action.  The sensitivity is assigned as follows:

sensitivity={0|16|32|48|64|80|96}

An example may be a style which checks the user's IP address and then blocks or redacts the content of a notification if the user is not on their corporate LAN.

Assigning a Default Callback

Each notification may have a default callback.  This is something that is either launched by Snarl on behalf of the application or something which is returned to the application as an event.  Either way, the event is triggered by the user "invoking" (clicking on the main body) a notification:
  • Static callback: This can be a URL or a path to a file or folder.  When the notification is invoked, Snarl will launch the URL or file on behalf of the application.  This can be useful for applications which cannot easily handle events from Snarl.
  • Dynamic callback: A dynamic callback is something which Snarl sends back to the application as an event.  This can be useful when the application wants to manage numerous notifications as the callback value can (for example) be used to identify a specific notification.  Exactly how the event occurs depends on the transport in use.  Dynamic callbacks are identified by an '@' symbol as the first character.  For example: @1234 or @mail::{01234567-89AB-CDEF}.
  • System callback: This is similar to a static callback in that it's both handled by Snarl and doesn't generate an event.  System callbacks cause Snarl to take some action, such as showing its Preferences panel.  System callbacks are identified by an exclamation mark as the first character.  For example: !run or !shutdown.
Irrespective of the type of callback used, it always assigned as follows:

callback={static callback|@dynamic callback|!system callback}

You should consider carefully whether it's appropriate to include a default callback.  Typically, a user will simply click on the notification expecting to dismiss it; if doing this causes some action to occur - for example opening a URL in a web browser - this is likely to have a negative impact on the user.  See the Notification Guidelines for more information.

Including Actions

Actions can be used to augment the content of a notification.  For example, a "new email received" notification may add Open, Reply, Forward and Mark as Read actions.  If a notification is assigned at least one action, a gear wheel gadget will appear below the close gadget (see image below) when the mouse pointer is moved over the notification - clicking the gadget pops open a menu displaying the actions.


An application adds actions to a notification by including one or more action arguments to the notify command, as follows:

action={label,callback}

Each action has a label and a callback.  The label is displayed in the menu; the callback follows the same pattern as the default callback (see above) and thus can be a:
  • Static callback: This can be a URL or a path to a file or folder.  When the notification is invoked, Snarl will launch the URL or file on behalf of the application.  This can be useful for applications which cannot easily handle events from Snarl.
  • Dynamic callback: A dynamic callback is something which Snarl sends back to the application as an event.  This can be useful when the application wants to manage numerous notifications as the callback value can (for example) be used to identify a specific notification.  Exactly how the event occurs depends on the transport in use.  Dynamic callbacks are identified by an '@' symbol as the first character.  For example: @1234 or @mail::{01234567-89AB-CDEF}.
  • System callback: This is similar to a static callback in that it's both handled by Snarl and doesn't generate an event.  System callbacks cause Snarl to take some action, such as showing its Preferences panel.  System callbacks are identified by an exclamation mark as the first character.  For example: !run or !shutdown.
The following pseudo code creates the notification above:

// assume application registered as "application/acme-test"
sendrequest("notify?app-sig=application/acme-test&title=Launch detection&text=Indian Ocean station 4 has detected an unauthorised launch&action=Protest,@900&action=Ignore,@0&action=Panic,@911&action=Invoke Armageddon,@666")

Selecting each action causes the values 900, 0, 911 and 666 respectively to be sent to the application as SNARL_NOTIFY_ACTION events.

Including Custom Values

In addition to the standard arguments, an application can also pass custom values inside a notification.  These values may simply be useful if the style logs them, or they may be recognised by a specialised style and acted up accordingly.

In order to implement some form of standardisation, there are two types of custom value:
  • Pre-defined
  • User-defined.
Pre-defined values begin with a recognised prefix and should only be used to pass data of the defined type.  The following table lists the currently defined values:

Prefix Indicates  Assigned Names  Comments 
value-  A numeric value  value-percent
value-usd
value-celsius
value-integer
A percentage value (that is, something between 0.0% and 100.0%)
A value which should be interpreted as US Dollars
A value which should be interpreted as a temperature in Celsius
A value which should be interpreted as a whole number
colour- A colour colour-html
colour-rgba 
Web format (e.g. #FF00FF)
Comma-separated Red, Green, Blue and Alpha channels 
label-  A string value label-suffix   
       
       

User-defined values begin with either data- (for private data to be passed from an application to a bespoke style) or x-app-{app}-, where {app} is the name of the sending application, for data from a specific application.  Some examples might be:

data-customer_ref=0123456789
data-transaction_date=2012/02/02
x-app-snarss-feed_last_refreshed=2012/01/21 19:05:23
x-app-outlook-mail_uuid=::ABCDEF01234567890

Furthermore, developers can request blocks of x- prefixed values to be assigned for their use.  Once approved, these blocks will then be included in the pre-defined values section above.

Updating Notifications

o

Merging and Replacing Content

o

Unregistering

When your application exits, it should unregister with Snarl.  This removes it from the list of registered applications and allows Snarl to free resources it may have allocated while the application was running.

Applications unregister using the unregister command, as follows:

unregister?app-sig=application/x-vnd-acme.some_app

If a password was used when the application registered, the same password must be used to successfully unregister.

Advanced Topics

Application Passwords

Introduced in V43 of the API, application's can provide a password then they register with Snarl.  The password is then used to prevent other applications from creating notifications by masquerading as an already registered application.   Once created, the password must be included in all requests sent to Snarl in order for them to be accepted.

The recommendation is that the password should be generated dynamically by the application on launch and should use a string of randomly generated alphanumeric characters.  The Snarl Framework takes care of password creation automatically, and many libraries and helper modules include macros for doing this.

Tidy up after yourself: if an application fails to unregister with Snarl when it exits, it will remain registered with Snarl until the periodic garbage collection runs and automatically unregisters it.  During the period between the application disappearing and the garbage collection running, any subsequent registrations will effectively be treated as re-registrations and, unless the application uses the same password it did on it's previous registration, it will not be able to register with Snarl.

Handling Events

An event is something which happens asynchronously to your application's program flow.  There are two types of event: those generated by the user interacting with a notification your application has displayed and those generated by Snarl itself when either it's running state or the user's presence has changed.


Two types:
callbacks from a notification when clicked, closed, action selected, etc.
events from Snarl when it starts, stops, etc.



Icons

icon={path_to_icon|url_to_icon|!stock_icon|#HICON|path_to_resource,index}

From HICON, resources, etc.

Base64 / Phat 64 encoding.

icon-phat64={base64_encoded_bytes}

The former method is preferred as it keeps the length of the request down, and no time is spent encoding and decoding the icon data.  However, if the n
'''icon-base64''' should contain the icon data encoded using MIME (Base64).  When supplying MIME encoded data, any trailing '=' characters must be replaced by '%' symbols before passing to Snarl as the equals signs will confuse the request parser.



Snarl-Specific Applications

Or SSA's as they're known :)


Working With Scripted Applications

Scripted applications are those which utilise interpreted languages over those which compile code into an executable block.  Scripted languages offer many advantages over compiled programs - not least as they are usually very lightweight, applications are quick to developer and - most of all - invariably free to purchase.  The most obvious scripted languages are MS-DOS and VBScript, although may more are available.

For all their simplicity, scripted languages tend to lack the ability to receive events.  This means that recognising when Snarl launches or terminates, when a notification has been invoked by a user, etc. are difficult - if not impossible - for a scripted language to implement.  When it comes to signalling a notification has been interacted with, there are some options: the script could simply supply a command or URL to launch, or the name of another script to run; recognising when Snarl launches or terminates however is not so straightforward.

At the present time, the recommendations for using Snarl from scripted applications are as follows:
  • Register with Snarl each time a notification must be displayed: Registering is a single command and creates little additional overhead with Snarl.  This ensures that your script will always be registered with Snarl before the notification is displayed;
  • Avoiding using a password when registering (or always use the same password): This allows for repeated registrations by the script without corresponding unregistrations.  Registrations are not nested by Snarl, however passwords must always match the currently successful registered password.
Further improvements are planned in this area and this section will be updated accordingly.

Notification Guidelines

Rationale

Frequently applications will need to alert the user about certain events. These events can be blocking (modal) whereby normal application execution cannot continue until the user has either acknowledged the event or selected an option to proceed with. An obvious example of such an event is an application querying if the current document should be saved or discarded. Some events, however, do not need the user to explicitly acknowledge them, or to select an option - these events are non-blocking and could include notifying the user that they have a new email, the battery on their device is getting low, a new contact has signed in, and so on.

For the latter category of notification, modal dialog boxes are both unintuitive and unsuitable in a multi-tasking environment and, as such, different options must be considered, including:
  • Displaying a non-blocking floating window;
  • Displaying a notification balloon in the Windows notification area;
  • Displaying a bespoke pop-up or otherwise animated window.
All of the above have individual flaws and also require additional code to be added to the application. Furthermore - and probably worst of all - none of these methods allow for user customisation of how (or, indeed, if) the notification is displayed.

Where a user receives a notification is becoming more important as well. It is perfectly conceivable that a user may which to be emailed, be sent an SMS, or receive a push notification that notifies them that a particular event has occurred. An example would be a developer who sets his project compiling and then leaves for a coffee break - he or she would want to be notified that the compilation succeeded or if any errors were detected, and they would want to receive when away from their workstation.

A single service which takes care of all this is a necessity. Having a single service:
  • Reduces the requirement for application developers to craft their own notification handling code;
  • Provides a consistent interface to the end user;
  • Extensibility (i.e. the ability to have new ways of notifying a user) can be provided by plugins or add-ons to the service;
  • The user is empowered to determine how all event notifications are handled from a single point.

Use Cases

In addition to the problem of how a user should be notified of a particular event, it's also a question of allowing the user to decide when they're notified of a particular event. Take the following scenario:
  • Bob is preparing for a presentation to the senior management team
  • He's checking a few last minute issues with Sarah via his IM application
  • Bob begins his presentation
  • Five minutes in, Sarah sends him a "Good luck!" message via IM
  • Twenty minutes in, Bob's laptop battery drops to 10% charge left.
In this scenario, Bob would not want to be disturbed by Sarah's IM message but he would most definitely want to know that he'd forgotten to plug his laptop in and that the battery was getting low. This highlights the need to for contextualisation of alerts - in this case, Bob would enable Do Not Disturb mode ensuring that priority notifications (the one about his battery getting low) would still be displayed while others (Sarah's friendly but unwanted) IM wouldn't.
In order to maintain a consistent appearance, your application should follow these guidelines.  They're not meant to be restrictive; instead they are recommendations.

Inside the Notification

Title and Text

  • Keep the title and text short: Notifications appear at random times and, as such, the user will want to be able to digest the meaning of the notification as quickly as possible.  Titles should be kept as short as possible, typically no more than 4 words; the notification text may be longer but should still be as concise as possible.  If you need to pass a lot of information to the user, consider using a static callback or action which will direct the user to a document that contains it.

Icons

  • Use icons wherever possible: icons are multi-lingual and can convey greater meaning with less effort.
  • Choose wisely: a well-chosen icon can convey the meaning of the notification without the user having to read the associated text.

Outside the Notification

Dynamically Modifying Notifications

  • Avoid programmatically hiding notifications: The hide command should be avoided as it is impossible for your application to tell whether the user has been able to fully digest the notification content.  The only time hide may be of use is if the event the notification is alerting the user to no longer exists (for example, a "power disconnected" notification when the power supply has been restored).

Priorities

  • Avoid high-priority notifications: Generally speaking the user should be left to determine which notifications constitute high-priority status.  When deciding whether a notification should be displayed as high priority or not you should consider the context your notification will be displayed in and that, although you may feel the notification requires urgent from the user, the user may disagree.

Do Not Disturb (DND) mode can be enabled manually by the user or Snarl can be set to automatically enable it if the foreground application appears to be running in full-screen mode. In addition to this global on/off switch, the user can also define which notification classes should be treated as priority notifications so, in reality, all your application can do is recommend which notification classes should be treated as priority; the user has the final say in the matter.

Duration

  • Avoid sticky notifications: notifications which do not disappear automatically quickly take up screen space and can be frustrating to the user as they must then stop what they're doing, navigate to the notification and dismiss it manually.  The process is compounded if the notification has a default callback as the user must navigate specifically to the Close gadget on the notification - a much smaller area of screen than the notification itself.  
  • Use the Snarl default duration: there are very few examples where using something other than the default notification duration is suitable and using the default duration ensures consistency across notifications.