Copyright (c) Hyperion Entertainment and contributors.

Application Library

From AmigaOS Documentation Wiki
Jump to navigation Jump to search
WIP.png This page is currently being updated to AmigaOS 4.x. Some of the information contained here may not yet be applicable in part or totally.

Introduction

The Application Library is a multipurpose auxiliary library that provides various functions related to the development and use of applications. The very concept of application is a relatively recent addition to AmigaOS. Before, the system only distinguished between different types of program on a very low level, seeing them as either tasks or processes. This distinction might have been useful in the past when tasks (which require fewer resources in return for not being able to access DOS functions) could improve system performance. But it can hardly make a difference on today’s hardware so the trade-offs are no longer worth it. Nowadays it makes more sense to discriminate between programs that operate without the user even noticing (e.g. drivers, handlers, filesystems and other background services), and genuine full-blown applications with GUI and all.

AmigaOS alone cannot make such a distinction: it uses the Application Library as a mediator through which applications introduce themselves to the system. This process is called application registration, during which the application receives a unique identifier and is added to a public list among other applications. Once registered, the application can make use of the library’s many features:

  • It can send/receive messages to/from other registered applications. The library supports a set of common control messages (commands) such as those telling an application to quit, iconify or bring its window to front. But it also allows custom messages designed for an application’s particular needs; in this respect the Application Library provides an alternative to ARexx control.
  • It can use PrefsObjects, an XML-based, object-oriented system for handling program preferences. Before AmigaOS 4.x no real standard existed for storing preferences: some developers used icon tooltypes, some used proprietary formats, text or binary. The Application Library provides a format that is human-readable and easily editable in a simple text editor; that is comprehensive enough to cover even very complex settings structures; and that is fully controllable via the library, without the need to laboriously implement data parsing and verification.
  • It can notify the user about, for example, completed tasks via automatic pop-up messages. These represent a practical, less obtrusive alternative to traditional requesters.
  • It can easily create and manage lists of recently-used documents.
  • It can register as a unique application, preventing other instances of itself from running.
  • It can show its icon or display the current program state in taskbar-like applications, such as AmiDock.
  • It can control the behaviour of screen-blankers. Applications that don’t want to be disturbed may prevent the blanker from kicking in, or tell other applications to “keep quiet”.

Library opening chores

Just like other AmigaOS libraries, the Application Library must be opened before it is used. Further, at least one of its interfaces must be obtained, depending on the functionality you require. The Application Library has two interfaces, called “application” and “prefsobjects”. You always need to obtain the “application” interface because it provides access to most library functions including application registration. You’ll only need to open the “prefsobjects” interface if you intend to make use of the PrefsObjects preferences system.

struct Library *ApplicationBase = NULL;
struct ApplicationIFace *IApplication = NULL;
struct PrefsObjectsIFace *IPrefsObjects = NULL;
 
if ( (ApplicationBase = IExec->OpenLibrary("application.library", 52)) )
{
   IApplication = (APTR)IExec->GetInterface(ApplicationBase, "application", 1, NULL);
   IPrefsObjects = (APTR)IExec->GetInterface(ApplicationBase, "prefsobjects", 1, NULL);
}
 
if ( !ApplicationBase || !IApplication || !IPrefsObjects )
{
   /* handle library opening error */
}

Note that there is no interface called “main” like older, single-interface libraries have.

When your application has run its course, don’t forget to clean up and close both the library and its interface(s):

IExec->DropInterface((struct Interface *)IPrefsObjects);
IExec->DropInterface((struct Interface *)IApplication);
IExec->CloseLibrary(ApplicationBase);

Registering the application

Application registration is a simple process during which a program informs AmigaOS that it should be treated as an application, and provides some basic information about itself: the program name, an associated URL address, or a short description. Also, certain application-related parameters can be set at registration time (although some of these may be provided or changed later). Registration typically takes place at program startup; unregistration is normally done at the end of program runtime.

Application identifiers

A successfully registered application receives a numeric identifier, which in this documentation will be referred to as appID. Other registered applications can obtain the appID from the library and use it to communicate with the respective application. AppIDs are unique numbers: the Application Library generates them incrementally on a per-registration basis. They are never used again during the same AmigaOS session, which prevents programs from incidentally addressing the wrong application after the original appID holder unregisters.

Apart from the numeric appID an application can be referred to by its name (that is, a string-type identifier). As programs can get registered in an arbitrary order, it is the name identifier that other applications must use to retrieve the correct appID. To construct a unique name, the Application Library uses a special naming scheme that combines the application name with a related URL identifier (for example, the domain name of the application’s homepage). The latter is optional but it’s recommended to provide it at registration time, to avoid possible application name conflicts. The same naming scheme is used by the library’s PrefsObjects system to create the name of the preferences file.

Registration

Now let’s say we have a program called Best App made by the fictitious software company SuperCoders, Inc. The piece of C code to handle its registration might look like this:

uint32 appID;
 
appID = IApplication->RegisterApplication(“BestApp”,
           REGAPP_URLIdentifier, “supercoders.com,
           REGAPP_Description, “The best application there is, really”,
           TAG_DONE);
 
if (!appID)
{
   /* report registration error and quit */
}

Note that we’ve had to alter the application name to “BestApp”; it is because the Application Library doesn’t allow spaces in application names. According to the naming scheme, the application will now become registered under the name “BestApp.supercoders.com”. (Should a previous instance of BestApp be already running, the library will automatically append an instance counter to the application name: the second instance will therefore be called “BestApp_1.supercoders.com”, the third will register as “BestApp_2.supercoders.com”, and so on.)

The REGAPP_Description tag in the registration function tells the system what Best App is all about; it’s just an example of an optional parameter that can be provided. There are parameters that can only be applied at registration time, others may be set or changed later using the function SetApplicationAttrs(). Please refer to the Application Library autodoc for a complete list and description of registration/configuration parameters and their corresponding tags.

Unique applications

A program can register as a unique application, thus only allowing one instance of itself to run. While the multitasking nature and tradition of AmigaOS would suggest not imposing such limits, there can be good reasons to do so. For example, the developer of a song player might decide to make his/her program a unique application because the user would most likely gain nothing from playing several songs at the same time. Multiple program instances would only compete for screen space and system resources, possibly jeopardizing OS performance on lower-specification computers.

The following function call registers our Best App as a unique application:

appID = IApplication->RegisterApplication(“BestApp”,
           REGAPP_URLIdentifier, “supercoders.com,
           REGAPP_Description, “The best application there is, really”,
           REGAPP_UniqueApplication, TRUE,
           TAG_DONE);

If the user now tries to launch a second instance of the program, it will fail on RegisterApplication() and the library will send a special message to the first instance informing it about the attempt. It is the developer’s responsibility to react to this message in a sensible way. Do not show error messages here: the user doesn’t need to know (or care) that an application is unique, so an error message would scold them for doing nothing wrong. The recommended behaviour is to bring the first instance to front and activate its window. See the Messaging section below for more information.

Finding applications

The Application Library maintains a list of all registered applications. Certain special-purpose programs – let’s call them application managers – will also keep track of applications registering and unregistering. Nevertheless, most programs won’t ever have to do anything like this. If the need arises to talk to another application, they can simply find this particular application in the system and then start sending messages to it.

“Finding an application” basically means obtaining its appID from the library. To do this you need to know at least one of the following:

  • the application name, ie. the one under which it was registered via RegisterApplication();
  • the application name identifier, ie. the unique combination of the application’s name, instance number (should there be more instances running) and URL identifier – see Application identifiers above;
  • the pathname pointing to the program file on disk, e.g. “Work:Utils/BestApp”.

Based on this information, the respective piece of code that will find our BestApp in the system might look like this:

uint32 appID;
 
/* if you only know the application name */
appID = IApplication->FindApplication(FINDAPP_Name, “BestApp”, TAG_DONE);
 
/* if you know the application name identifier */
appID = IApplication->FindApplication(FINDAPP_AppIdentifier, “BestApp.supercoders.com, TAG_DONE);
 
/* if you specifically want to talk to the second running instance */
appID = IApplication->FindApplication(FINDAPP_AppIdentifier, “BestApp_1.supercoders.com, TAG_DONE);
 
/* if you know the pathname to the program file */
appID = IApplication->FindApplication(FINDAPP_FileName, “Work:Utils/BestApp”, TAG_DONE);

Once you have obtained the appID you can start communicating with the respective application.

Messaging

(to be continued)