TweetFollow Us on Twitter

Location Manager Pref Treatment

Volume Number: 13 (1997)
Issue Number: 9
Column Tag: develop

Preferential Treatment Under Apple Location Manager

by Erik Sea

Apple Location Manager (ALM) is a suite of system software enhancements that shipped in January, 1997, but unless you're a PowerBook user, you may not have seen ALM in action. Later this year, however, you'll see a completely new version that works on any Mac OS 8 computer, be it large or small, battery-powered or tethered to the electrical grid. With increased availability, it's become even more practical to add ALM-savviness to those services, tools, and applications that need it, and over the next few pages we'll discuss some ways to do just that.

At the heart of ALM is the idea that many Mac OS users repeatedly fiddle with various control panels and change preferences. They make these changes for a number of reasons: a mobile user who travels from place to place needs to adjust to those different environments, while a home user might have different settings for telecommuting versus playing games. With ALM, the chore of going through and repetitively changing a large number of settings is reduced to a single Control Strip menu choice, once the collection of settings has been given a name. With this named collection of settings and actions, known as a "location" in ALM, lengthy lists of reconfiguration steps (some users even have these taped to their monitors or stuck to their keyboards) should become a thing of the past -- provided the software they need to configure is ALM-savvy.

Should you make your software ALM-savvy? Well, if you have a product that has preferences that the user can change, directly or indirectly, the answer is yes! You might think that your software's preferences are simple -- maybe not much more than a simple "on-off" or two that the user can change with a click, but, in the larger context, the user might want to turn your preferences on or off at the same time as changing something else -- batch reconfiguration is a surprisingly common activity. Consider turning file sharing on or off: file sharing is only useful when there is a network around, and users might forget to turn it off at 37,000 feet, but if they've defined a location called "Air Travel" that turns it off for them (and perhaps turns off AppleTalk and dims the screen for better power conservation), they might just get a few precious minutes of additional battery life over just dimming the screen -- but will they remember to do it? With ALM, they only need to remember the details when they create their locations -- from then on, they need only use those locations.

You might also think that your users generally don't change their preferences, and it's true that many don't. However, you may want to consider whether they would if it were easier and could be done in concert with other changes to their environment. Some applications nest their preferences so deep in subpanels that the utility of making the change is offset by the cost of making it -- but what if it were easier? I'm sure you're starting to see what I'm getting at.

There are many ways for your software to interact with ALM, including some I probably haven't thought of. I'll present some in my allotted space, but please do get in, explore, and create things that just make sense -- the ideas are simple, but the uses are numerous!

Ways and Means

A developer once commented to me that ALM is one of the simplest, yet most complex pieces of system software to come along in a while. While you may shy from such paradoxical remarks, they correctly reflect the continuum of development options at your disposal -- ALM-savviness can take many forms, ranging from tight integration with your software to standalone ALM modules written by third parties for your products.

One of the first ALM modules written outside Apple was an ALM module for Apple's OT/PPP developed, as shareware, by Prime Computing Systems and available on the web at

ALM modules are generally self-contained preference-swappers that cooperate to varying degrees with the software that owns the preference in question. The tighter the integration, the better the user experience, but you can certainly start out with looser coupling and improve it as revisions to your product permit. ALM modules implement some or all of the ALM module API, and are placed in the Location Manager Modules folder, inside the Extensions folder. I'll discuss module development shortly.

There are other types of ALM modules, called action modules, that, rather than swapping preferences for a piece of software, perform an activity that may or may not be associated with a specific piece of code, but just automate the process of doing some sequence of steps during a location switch: opening a file, for example. For more on action modules, and the slight differences between their API and the API of standard modules (for example, one of the "optional" calls for a standard module becomes "required" for an action module), see the ALM SDK.

To find the latest ALM SDK, go to our web site at, or see the Mac OS SDK on CD. To take advantage of the newer features of ALM 2.0, be sure you're using the SDK's interfaces and libraries -- older versions of these components may have come with your development environment, and don't have all of the new features. See "Whatcha Got?" for information on testing for the availability of features.

The ALM engine -- that is, the part that provides the core services related to switching -- has a public API that developers can use to enumerate the user's locations, create new locations, or switch locations. We'll cover the ALM API later.

Finally, although ALM modules can provide a great deal of flexibility to a developer who wishes to become ALM-savvy, but there are cases where a piece of software might benefit from a deeper knowledge of what the engine is doing. There is the API, as mentioned earlier, but you should know that it can be used in clever ways that might be appropriate for some software that would benefit from even tighter integration with ALM. A hypothetical example of this kind of location-awareness, going beyond mere ALM-savviness, is discussed in the latter part of this article.


As with any system software from Apple, there are means for testing what features are present in ALM, since the features have changed from version 1.0 to 2.0.

This selector returns the version of the ALM engine that is installed on the machine.
This selector returns a bitfield representing engine functionality with the following bit meanings:
  • gestaltALMPresent is on if ALM is installed; it's possible, on some hardware, for the selector to be defined but for this bit to be off, so check!
  • gestaltALMHasSFLocations is on if the Get, Put, and Merge location calls are implemented.
  • gestaltALMHasCFMSupport is on if the engine recognizes CFM-based modules, otherwise only Component Manager modules are directly supported.
  • gestaltALMHasRescanNotifiers is on if notifications for changes in the names or number of locations will be sent via callbacks and Apple events; otherwise, only notifiers for switches are generated.

With so many options to choose from, it might take a while to figure out how your software and ALM might collaborate. So, as you dive into the rest of this article, keep in mind that there is often more than one path to ALM-nirvana, er, savviness, but the sooner you start, the sooner you'll arrive. Setting aside philosophical opinion, let's look at the path most traveled first.

Magnificent Modules

For most situations, the ALM module provides the easiest and best-encapsulated way to get your software plugged into the ALM engine. The calls that an ALM module supports are very general: a module (or any software it interoperates with) doesn't need to know anything about locations or how the ALM control panel works, just how to interact with the software it represents.

Just What Is A Module Anyway?

It is difficult for me to describe what an ALM module is or does without showing how the user interacts with them. To define a location, the user runs the ALM control panel, and picks "New Location" from the File menu. All location editing is done from the main window, seen in Figure 1. In the top part of the window, we see the current location (that is, the location a user switched to in the past or the location the user is "in" right now) specified by a pop-up. The user can switch from this pop-up or switch from a similar menu in the control strip.

Figure 1. Apple Location Manager main window, in expanded mode.

The disclosure triangle toggles display of the bottom half, where a second pop-up shows the name of the location to be edited. As you can see, it's possible to edit locations that are not the current location, which creates some special issues you might have to deal with. More on that later.

At the left side of the window, we see a list of modules that ALM knows about -- they are located in the Location Manager Modules folder. Each of these modules has a value associated with the edit location, and a description of that value is displayed at the right when the associated module is selected at the left.

Modules are ordinarily listed in alphabetical order, and the list order is the order that the engine applies changes when switching. The user can, using menu options, move modules around in the list to achieve different results (it's often handy, for example, to have modules that might require a restart, such as Extension Set, first, so that other modules, such as Auto-Open Items, could decide to defer execution until after the restart).

Modules could also be in the list several times if the user has chosen to duplicate them (another menu option). For example, a user might have several instances of Auto-Open Items sprinkled throughout a location definition, doing everything from mounting servers to executing AppleScript scripts.

The value for a module within a location is saved whether the module is on or off -- this allows the user to temporarily alter the location by excluding a module's setting without losing the settings established for it.

Only a few calls are necessary to support everything seen in the control panel.

If you're concerned about supporting ALM 1.0, rest assured that, despite the vast difference in appearance of the control panels, ALM 2.0 calls modules with the same expectations as its predecessor, but if you want to work under both versions, you'll have to take care not to use any 2.0 features. The bottom half of the new control panel corresponds to the separate Edit Location window in the old control panel, and the new "on-off" checkbox corresponds to "adding" a module to a location in 1.0. There's some information displayed in the old interface that isn't anywhere in the new one for simplicity and performance reasons.

What A Module Needs To Know To Do

Essentially, an ALM module only needs to know how to interpret the settings of the software it supports, how to change those settings, and how to get those changes recognized. We'll discuss nuances in a moment, but here are the calls a module absolutely must handle (for both ALM 1.0 or 2.0).

pascal OSErr GetCurrent (Handle setting);

When a module receives this request, it resizes the handle to whatever size is necessary to store the current setting. It is generally a good idea to "version" this information, in case you decide to change it later. In addition to the version you should also store in the handle enough information to restore the setting when ALM calls your module with the handle at a later time. This handle is stored on disk in a location file, so be sure you've "flattened" it out (that is, there are no pointers to things in memory that might not be in the same place when your module is next called).

pascal OSErr SetCurrent (Handle setting, ALMRebootFlags* flags);

Modules receive this call during a switch. The setting will be one which your module has previously returned from a GetCurrent call, though, obviously, it may have been stored some time ago. Be aware that, because ALM allows a user to switch location very early in the boot process, you need to check for things that may not be around yet (such as the Process Manager). If the environment is too hostile for your tastes, your module should return kALMDeferSwitchErr in response to this call, and ALM will try again later in the boot process.

The flags parameter is used to communicate to the engine what the impact of the setting change was, so that the user can be offered the opportunity to restart, if necessary. Possible responses include kALMNoChange if the settings did not actually need to be changed, kALMAvailableNow if they can be used immediately, or kALMExtensions if a restart is required (in which case the user will be given the option to reboot their machine) -- see the SDK for additional values and their meanings. Note that the input value of the flags parameter is the current escalation of the switch process, as set by previous modules. If the reboot level is already too high, you can set the flags to whatever value is appropriate for what you actually did, and return kALMRebootFlagsLevelErr as the function result.

The input value of flags in ALM 1.0 is always kALMNoChange, and there is no way to determine what the reboot escalation level is when you are called. You shouldn't return kALMRebootFlagsLevelErr if the input escalation level is kALMNoChange unless you know you're under 2.0.

You should avoid forcing the user to reboot when they switch your settings -- your customers will thank you for saving them time and trouble. Possible strategies include defining an Apple event or other signal that your software will recognize as "read your preferences now", then send that signal from your module's SetCurrent function.

pascal OSErr CompareSetting (Handle setting1, Handle setting2,
                                      Boolean* equal);

This call is made to determine whether two settings represent the same values from the point of view of the module. This is used at different times and in different ways, and has a special interaction with the optional EditSetting call, discussed later.

You'll find that this call is made less often under ALM 2.0 than it was under the older version, because of UI changes, but ALM 2.0 still requires it.

pascal OSErr DescribeSetting (Handle setting, CharsHandle text);

Generate a textual description for one of your settings, resizing the CharsHandle as appropriate to fit the text. Don't go overboard in your description -- the window containing the description is resizeable, but try to fit your description in the minimum window size for best results. The script system used will be that returned by the GetScriptInfo call, described shortly.

pascal OSErr DescribeError (OSErr lastErr, Str255 errStr);

You are encouraged to return your own (positive) error response values from a module API call, and you'll get first crack at telling the user what they mean. If you don't wish to describe an error, return paramErr in response to this function, and the control panel will present it to the user as a number (boo, hiss).

pascal OSErr GetScriptInfo (ALMScriptManagerInfoPtr info);

This call, though technically optional, is pretty easy to implement, and is recommended if you expect your module to be used worldwide. The format of info is as follows:

typedef struct {
        SInt16      version;
        SInt16      scriptCode;
        SInt16      regionCode;
        SInt16      langCode;
        SInt16      fontNum;
        SInt16      fontSize;
} ALMScriptManagerInfo;

You should set the version to kALMScriptInfoVersion, and fill in the font and script manager information in accordance with how you wish your text to be displayed. If you don't do this, you might not play well in other languages, because the system will fill out the script information on your behalf, and your module might end up getting displayed in the wrong script -- certain characters do not translate well, to say the least. It is actually possible for modules to be of different script systems yet be displayed correctly. If you plan to localize your text, you'll probably want to put script information in a resource that gets localized at the same time. See the sample code in the SDK for a good strategy to do exactly that.

pascal OSErr GetInfo (CharsHandle* text, STHandle* style, 
                 ModalFilterUPP filter);

The GetInfo call is made to tell the user what your module is all about, such as what other software it interacts with. There are essentially two flavors to this call: in the first, you simply return styled text using the first two parameters, and it gets displayed, as shown in Figure 2. The text can be any length, but don't write a book -- say what your module does, what software it works with, and where to go for more information.

In the second flavor of GetInfo, the module itself takes care of displaying whatever dialog it chooses, or perhaps opens an AppleGuide window, and returns NULL in the first two parameters to signal that it did the job on its own.

Figure 2. Control Panel Displays Results of GetInfo Call.


At first glance, it may seem that ALM modules and AppleScript are two technologies vying for the same role, for if every preference-generating piece of software were scriptable, an intelligent user could just have a collection of scripts to effect a location switch.

If you look deeper, though, you'll see that these technologies are complementary: a totally scriptable control panel, for example, even if it were recordable, would benefit from the centralized, simplified process of location definition and aggregation with other settings. At the same time, it is much easier to support ALM in a control panel that has already been made scriptable because the requisite code factoring makes ALM support a breeze.

Still, you do not need to be scriptable to support ALM, and, though I would prefer that you did make your software scriptable, you don't need to do it for ALM.

The filter parameter to the GetInfo call is a legacy parameter, used only in ALM 1.0. ALM 2.0 does not require you to call filter explicitly, but you may do so.

Those are the basics; the SDK provides a good sample implementation you can start from, in the form of the "Generic" module, which is particularly handy for prototyping.

In fact the Generic module could theoretically be used with only a few changes in resources, and, for some limited-use applications, or for prototyping, that might be enough, but it's probably not up to the quality required for commercial or even shareware release.

Though these calls are enough for ALM to work correctly and predictably, there has yet to be an API devised whereby you can become "savvy" by supporting just the lowest level, so let's go up a step.


Over the last little while, people have begun to recognize the value of storing named configurations, or sets of preferences, for easier retrieval by users. This is a good thing, and is a move in the direction of ALM. An ALM module that deals with a piece of software that already supports named configurations probably just needs to track the name, and that makes life much easier, because you basically are dealing with just a reference to other data, rather than the other data directly.

There are, however, complications, such as the need to define dual formats for your settings: normal (in which case a reference to other data on the current machine is adequate) and import-export (in which case you need to recreate the entire setting for use on another machine).

Another question is what happens if the user changes the named configuration -- will your module know how to track the change and update its reference?

And how will your module help Bob import "My Reactor Settings" from Anne's computer, without wiping out his existing (and potentially different) "My Reactor Settings"? Maybe he really wants to replace them, but maybe he wants to rename the import as "Anne's Reactor Settings".

You'll have to solve the reference-tracking problem for yourself, but ALM does provide a call to handle import name collisions, called ALMConfirmName, discussed in the API section.

Of course, if your setting is very simple, such as on or off, both formats of your setting can be the same, and your implementation of ImportExport becomes very simple -- just return noErr.

What A Module Should Know To Do

With some additional work, you can provide the user with additional ALM-supported functionality and achieve ALM-savviness. The capabilities you'll need to tackle are editing of inactive settings, and import-export. If you don't implement these functions to at least some extent, not only will you fail to enter the blissful state of ALM-savviness, but your customers may become confused and you'll have a recurring dream in which you read Inside Macintosh: AOCE Application Interfaces word for word, from cover to cover, until your conscience makes you support these added functions.

This setting must change - As mentioned earlier, it's possible for a user to edit the settings from one location while being in another. Through use of the "Apply" button (refer to Figure 1), the user can change a setting in a location by capturing the current value of the setting on the computer. This is done through the GetSetting call described previously. In user studies, we found that it's highly desirable for the user to be able to change settings in an inactive location without changing the live system settings (we do provide a way to reassert the current location's values). Unto this desire, the EditSetting call was born.

pascal OSErr EditSetting (Handle setting);

The EditSetting call is optional, but very strongly recommended. The input setting parameter is one that will have come from an earlier call to GetCurrent. Do whatever you need to do to edit the setting, and return either the same one (if the user cancels the edit) or a different one (if the user accepts the edit). When I say different, I mean different enough that your CompareSetting call will say, "Yes, they're different" -- if there was no real change, your module might just flip a bit in the setting handle that it would ignore everywhere but on a CompareSetting call. The reason for requiring these settings to seem different even if they aren't is a subtle bit of UI trickery in the ALM control panel: the control panel will automatically turn a setting on if, as a result of an EditSetting call, it can be ascertained that the settings were accepted by the user. The control panel makes the determination of acceptance based on the input and output setting handles being different.

Implementing the EditSetting call can be done in a number of ways. Ideally, an EditSetting call would bring up the same interface you use in your software to edit your live preferences, but without affecting those live preferences -- a sort of "preference UI factoring", if you will. Alternatively (but less desirably), you can take some sort of middle road, ranging from explaining to the user where they should go to edit their live system settings (and reminding them to put those settings back the way they were), to providing a little "platform" from which to launch your software, perhaps under AppleScript control.

The EditSetting call was supported under ALM 1.0, and, in fact, it's required for action modules. There is, alas, no support for EditSetting of standard modules in the old control panel, so be aware of that limitation if you plan to support both versions of ALM.

If you don't implement EditSetting, the ALM control panel has no way of knowing where your setting comes from, so it displays the message shown in Figure 3 when the user tries to edit your setting.

Figure 3. Developer Raspberry: Module does not support EditSetting.

I can't encourage you strongly enough to implement EditSetting to some extent in your initial release, and then refine it over time (if you don't go all the way up front). I've seen hours of videotaped user experiences, and the EditSetting capability more closely reflects how users expect the machine to behave, so don't let them see this brick wall of an alert when they use your module.

Duties Paid: Importing and Exporting

It would be really nifty for a user if, once they've honed a location to near perfection, they could share it with others. It would also be nice if, walking into a new environment, a user could receive a group of settings that other people in that environment use. That, in a nutshell, is what the ImportExport capability is all about.

pascal OSErr ImportExport (Boolean import, Handle setting,
                      SInt16 resRefNum);

The settings dealt with by most of the API can be small -- they may just be references to other data structures (I would encourage this design decision, though it introduces some new issues as discussed in "Dualing Settings"), and that will work fine on one user's computer. If you were to export just the name, however, the importing machine might not be able to interpret it correctly.

So, when you export, you might want to augment the setting handle with additional information that would allow you to replicate the setting on another machine (short of actually installing software on that machine!), and, on import, you can decode that information and shrink the handle back down to size. If that technique isn't enough, or you'd rather keep your setting the same, you can add resources to the exported location file, and read them in on import (after you read your resources in, you should delete them, since you're actually working on a copy of the import file, in the Locations folder, rather than the actual import file). You should use a unique resource type, such as your creator, for the resources you use.

If you don't implement ImportExport, be sure to document this in your GetInfo window information.

Now that you know how modules work and how ALM calls them, let's go to the other side of the fence and see how to call ALM.

Start Your Engines!

The ALM API contains a series of calls for the developer to find out about a user's locations, a call to initiate switches, calls to create or let the user merge a setting into a location, plus events and notifications to determine when a switch has occurred or a location has been created. As mentioned previously, there is also a call to handle import collisions in a uniform way.


The ALM API is accessible in C, Pascal, or Assembly, from PowerPC or 68K, in classic or CFM-68K runtime models.

Since CFM-68K calling isn't available under ALM 1.0 I recommend weak-linking with the CFM-68K stub library and then testing against API symbols at launch.

What place is this?

If you want, you can take a gander at what the user has set up. Perhaps you want to build your own pop-up menu to provide the user the ability to switch locations from within your application, rather than the control strip or control panel. Here are the calls, and a very simple program to use them can be found in Listing 1.

Listing 1 Printing the User's Defined Locations

ALMToken                curLocToken, locToken;
ALMLocationName         curLocName, locName;
SInt16                  numLocs, locIndex;

printf ("User Locations on this Machine:\n");
err = ALMCountLocations (&numLocs);
printf ("There are %d locations in total\n", numLocs);
err = ALMGetCurrentLocation (NULL, &curLocToken,                 curLocName);
printf ("The active location is %s\n", 
            p2cstr (curLocName));
for (locIndex = 0; locIndex < numLocs; locIndex += 1) {
  err = ALMGetIndLocation (locIndex, &locToken,                 locName);
  if (locToken != curLocToken) // special treatment!
    printf ("Location %d is %s\n", locIndex, 
            p2cstr (locName));
    printf ("Location %d is the current location\n",               locIndex);
} // for
pascal OSErr ALMGetCurrentLocation (SInt16* index, 
                        ALMToken* token,
                        ALMLocationName name);
pascal OSErr ALMCountLocations (SInt16* locationCount);
pascal OSErr ALMGetIndLocation (SInt16 index, 
                        ALMToken* token,
                        ALMLocationName name);

The indices in these calls are zero-based, so the maximum will be one less than the locationCount. The special index value kALMNoLocationIndex denotes the situation where the user has chosen the special location "None (Off)". ALMTokens represent references to locations for use in other calls (and the special value kALMNoLocationToken corresponds to kALMNoLocationIndex). If you only want certain parameters to be returned, it's legal to pass NULL for any pointer.

Snapshots -- as Pretty as a Picture

In ALM 2.0, there are functions that you can use to interact with the user much like the control panel does. You should gestalt these functions (see "Whatcha Got?") before using them. The user experience is very much like the Standard File package, only simpler, but the calls themselves take care of a lot of additional work for you.

Sometimes, you'll want the user to simply choose a location from a list without need for iterating across all installed locations and building your own UI. To ask the user for a location, use the ALMGetLocation call, which presents a dialog as shown in Figure 4.

Figure 4. Asking the user for a location with ALMGetLocation.

pascal OSErr ALMGetLocation (ConstStr255Param prompt, 
                    Str31 locationName,
                    ModalFilterYDUPP filter, 
                    void* yourDataPtr);

The prompt is displayed above the list of locations, as in Standard File. The locationName is both an input and an output parameter -- if the name matches a location, that location will be selected in the list. The filter and data pointer are for your own use, again as in Standard File. If the user clicks cancel, the function result is userCanceledErr; otherwise, it should be noErr.

The next two calls, ALMPutLocation and ALMMergeLocation are intended to allow an application, such as a setup program, to capture the current system settings for a number of modules as a location, or merge them into an existing location. Detailed information on module signatures, or types, is beyond the scope of this article (see the SDK), but the use of some special values for these parameters is shown in Listing 2.

pascal OSErr ALMPutLocation (ConstStr255Param prompt, 
              Str31 locationName,
              SInt16 numTypes, 
              ConstALMModuleTypeListPtr typeList
              ModalFilterYDUPP filter, void* yourDataPtr);
pascal OSErr ALMMergeLocation (ConstStr255Param prompt,
              Str31 locationName,
              SInt16 numTypes,
              ConstALMModuleTypeListPtr typeList,
              ModalFilterYPUPP filter, void* yourDataPtr)

Listing 2. Put Up or Merge Up

// create a new, empty location
err = ALMPutLocation ("\pName your place", 
          "\pEmpty Location", kALMAddAllOff, 
          NULL, NULL, NULL);

// add to a location as a snapshot, using all currently-installed
// non-action modules, replacing current definitions
err = ALMMergeLocation ("\pRedefine your place",
          "\pSnapshot Location", 
          kALMAddAllOnSimple, NULL, NULL, NULL);


There would be very little use to ALM without the switch engine. This is the call that the control strip and control panel use to effect a change in location:

pascal OSErr ALMSwitchToLocation (ALMToken newLocation,
                        ALMSwitchActionFlags switchFlags);

Most of the time, you can pass kALMDefaultSwitchFlags for the second parameter. For a quiet switch (that is, one in which the switching dialog does not come up), pass the mask kALMDontShowStatusWindow. If you're making this call from an unusual place such as inside a dialog filter or some other weird place, use the mask kALMSignalViaAE so that the switch will be deferred until the ALM control panel (or the Finder, if the control panel isn't open) is in a better synchronized state.

If you wish to switch locations from a background application you should use either kALMDontShowStatusWindow or kALMSignalViaAE or both. If you do not, ALM 2.0 will return an error. ALM 1.0 is less forgiving, and will crash if the host application hasn't initiallized the window manager. Moral: don't use default flags except in direct response to a user action in your foreground application!

Noticing Switches and Other Goings On

One of the more interesting things about ALM is that it actually tells all running processes when the user has changed locations. Under ALM 2.0, it'll also advise when the user has created, renamed, or deleted a location, so that applications that want to know can rebuild any list of locations they might have internally, or reorganize any data they might have been shadowing on a location-by-location basis by rescanning the user's installed locations using a technique like that of Listing 1.

You should check gestalt for the availability of the rescan notifiers if you're going to rely on them, as described in "Whatcha Got?". If they are not available, you can employ alternate strategies, such as periodically iterating through the installed locations. In any case, it's good practice to recheck the installed locations at start-up if you save your own list somewhere.

Listing 3. Observing Switches and Handling

Rescan Notifiers
pascal OSErr MySystemConfigNoticeHandler 
              (const AppleEvent* inEvent, 
              AppleEvent* reply, SInt32 refCon)

  OSErr        err  = errAEDescNotFound;
  ALMToken      locToken;
  DescType      actualType;
  Size          actualSize;

  // Handle any other cases you like...
  // Did we get a switch notification?
  if (err != noErr) {
    err = AEGetKeyPtr (inEvent, 
            typeInteger, &actualType,
            &locToken, sizeof (locToken),
    if (err == noErr) MyDoReactToSwitch (locToken);
  } // if
  // Did we get a rescan notification?
  if (err != noErr) {
    err = AEGetKeyPtr (inEvent, 
            typeInteger, &actualType,
            &locToken, sizeof (locToken),
    if (err == noErr) MyDoReactToRescanNotice (locToken);
  } // if

  return err;

} // SystemConfigNoticeHandler

The class of the Apple event is kAECoreSuite, and the event ID is kAESystemConfigNotice, just as with the display manager's notifications that the screen size or resolution has changed. If your event handler receives such an event, and there is a parameter keyed under kAELocationChangedNoticeKey, then a switch has occurred, and that parameter's value is the ALMToken of the location to which the user switched. If there is a parameter under kAELocationRescanNoticeKey, then the user has made changes to the installed locations, and you can't rely on any of your previously stored data about locations being valid. The value of the parameter is the ALMToken of the current location. For a skeletal handler, see Listing 3.

Event Me Not

Of course, if you're a code resource, you won't be getting many Apple events, so you can provide a function such as this as an alternative:

pascal void MyALMNotificationRoutine (AppleEvent* theEvent);

Your implementation of this routine ought to be similar to the Apple event handler in Listing 3. Create a UPP by passing your routine to NewALMNotificationProc, and then register and deregister your routine using these calls:

pascal OSErr ALMRegisterNotifyProc 
                (ALMNotificationUPP notifyProc,
                const ProcessSerialNumber* whichPSN);
pascal OSErr ALMRemoveNotifyProc 
                (ALMNotificationUPP notifyProc,
                const ProcessSerialNumber* whichPSN);

The ProcessSerialNumber parameter is used by ALM to ensure that notifications aren't sent to code whose process no longer exists (but for which the notifier was not removed). You should pass the serial number you're associated with.

Import Collisions

Particularly if you implement named configurations, as discussed in "Dualing Settings", you could have situations, when importing, where a setting you're importing conflicts with a setting already on the machine. To address this problem, ALM provides a routine that displays two dialogs in succession. The first asks the user to choose either to rename or to replace the named configuration, and the second, shown in case of a rename, presents a box in which to rename the configuration. The call is as follows:

pascal OSErr ALMConfirmName (ConstStr255Param msg, 
                Str255 configName,
                ALMConfirmChoice* choice, 
                ModalFilterUPP filter);

If the user cancels the operation, the function returns userCanceledErr; otherwise, the value of choice is kALMConfirmRename or kALMConfirmReplace, depending on the user's choice. You may provide a filter function, if you wish access to events in the dialog. The refcons of the dialog boxes disclose which is which, and the individual element numbers are provided as constants in the ALM 2.0 interfaces, should you wish to do things like constrain the allowed characters in your configuration name (rather than validating the name after the call returns). For details on the refcons and item numbers, see the SDK.

Due to a bug in ALM 1.0 the filter function was not called in both dialogs, but just the rename dialog. If your filter function sees a refcon of zero, you can assume you are in the 1.0 rename dialog box.

AppleScript Support

Alternatively, you can access much of the API by sending AppleScript commands to the control panel. A simple switch through AppleScript is shown in Listing 4. You can, of course, also list locations from AppleScript using the Standard Suite.

Listing 4. Driving a Switch from AppleScript

set someLocationName to "Home Office"
tell application "Finder"
  set cpFolder to (control panels folder as string)
  open file (cpFolder & "Location Manager")
  tell application "Location Manager"
    set current location to location someLocationName 
  end tell
end tell

Though this API is small, these same bricks will build a house or a castle, depending on how you choose to use them. Although the water may look deep, location-awareness could represent the ultimate offering to the user, giving them much more than ALM modules, alone, are capable of.

Where Am I?

Thus far, we've talked about ALM-savviness and driving the engine, but now let's switch gears a little and talk about the greater generalities of location-awareness.

How a piece of software becomes location-aware is as unique as the piece of software itself -- it requires planning and thought beyond how to simply automate the chore of switching preferences. Instead, a location-aware piece of software has new functionality that its location-oblivious sibling does not.

As an example, let's take the Apple Menu Items control panel, which has been an indispensable part of Mac OS from System 7.5 to the present. What form could location-awareness take in this control panel (see Figure 5)? Suppose that, in each location (whether a "location" is a physical location or merely a state in which they perform different tasks), the user accesses different documents, applications, and servers that are specific to that location, but, in moving from one location to the next, they constantly wipe out recent items from one place before they get back to it. Typically, users faced with this problem combat it by increasing the recent item allocation numbers, but while searching through a big list works, it's far from ideal.

Figure 5. Mock-Up: Apple Menu Items with Location-Awareness.

We could just write a module for this that, through clever folder manipulation, swapped the recent items around, but what about the occasion when the user actually wants to access a recent item from another location without switching to that location first? Perhaps the submenus could present recent items in different ways -- the ordinary way most of the time -- or sorted by location if the user holds down the option key when choosing the Apple menu.

I am not suggesting that the hypothetical example I present above is the best possible answer, but I am hoping that software developers will consider using location-awareness as a new way to solve problems that their users might be facing.

Give location-awareness some thought -- it might be your best bet.

There's No Location Like Home

Now that you've been through savviness and awareness, modules and APIs, I hope you can see the opportunities ALM presents for you to make life easier for your users, both mobile and landlubber.

So take a few moments to install and play with ALM, and then play with the sample code. I think you'll be surprised at how much mileage you can get out of a very small amount of labor!

Thanks to my reviewers Mark Cookson, Dave Ferguson, Scott Johnson, Susan Michalak, Kent Miller, and Eric Slosser. Special thanks to everyone on the ALM team, present and past, for your contributions to shaping and sculpting a truly unique and innovative piece of software.

Related Reading

  • The ALM web page, located at
  • ALM SDK, available through the web site or on Mac OS SDK.

Erik Sea ( Erik arrived at Apple about a year ago, with the sole objective of inundating the PowerBook Division with slinkys -- so far, they remain confined to his office, except on weekends when they explore the building and feed on weak or infirm paper clips. When not tweaking Location Manager code or the ALM web site, he can be found volunteering his time to rearrange sets of encyclopedias so that the volumes run from right to left on the shelf (because that's the way the pages are aligned), or writing games in COBOL on his Apple ///+.


Community Search:
MacTech Search:

Software Updates via MacUpdate

Tor Browser 11.5.8 - Anonymize Web brows...
Using Tor Browser you can protect yourself against tracking, surveillance, and censorship. Tor was originally designed, implemented, and deployed as a third-generation onion-routing project of the U.... Read more
Alarm Clock Pro 15.0 - $19.95 (91% off)
Alarm Clock Pro isn't just an ordinary alarm clock. Use it to wake you up in the morning, send and compose e-mails, remind you of appointments, randomize the iTunes selection, control an internet... Read more
Google Chrome 107.0.5304.121 - Modern an...
Google Chrome is a Web browser by Google, created to be a modern platform for Web pages and applications. It utilizes very fast loading of Web pages and has a V8 engine, which is a custom built... Read more
calibre 6.9.0 - Complete e-book library...
Calibre is a complete e-book library manager. Organize your collection, convert your books to multiple formats, and sync with all of your devices. Let Calibre be your multi-tasking digital librarian... Read more
Safari Technology Preview 16.4 - The new...
Safari Technology Preview contains the most recent additions and improvements to WebKit and the latest advances in Safari web technologies. And once installed, you will receive notifications of... Read more
FileZilla 3.62.2 - Fast and reliable FTP...
FileZilla (ported from Windows) is a fast and reliable FTP client and server with lots of useful features and an intuitive interface. The FileZilla Client not only supports FTP, but also FTP over TLS... Read more
djay Pro 4.0.13 - Transform your Mac int...
djay Pro provides a complete toolkit for performing DJs. Its unique modern interface is built around a sophisticated integration with iTunes and Spotify, giving you instant access to millions of... Read more
Opera 93.0.4585.21 - High-performance We...
Opera is a fast and secure browser trusted by millions of users. With the intuitive interface, Speed Dial and visual bookmarks for organizing favorite sites, news feature with fresh, relevant content... Read more
AppCleaner 3.6.6 - Uninstall your apps e...
AppCleaner allows you to uninstall your apps easily. It searches the files created by the applications and you can delete them quickly. Supports macOS Ventura. Fixed an issue causing failed updates... Read more
QuickBooks - Financial manag...
QuickBooks helps you manage your business easily and efficiently. Organize your finances all in one place, track money going in and out of your business, and spot areas where you can save. Built for... Read more

Latest Forum Discussions

See All

‘Top Hunter Roddy & Cathy’ Review –...
The NEOGEO is generally characterized by, with only a few notable exceptions, fighting games and Metal Slug. Within a couple of years of its launch, the vast majority of the output on the console seemed to be mining (quite successfully) a few... | Read more »
SwitchArcade Round-Up: Reviews Featuring...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for November 28th, 2022. In today’s article, we’ve got a pair of reviews to check out. Full reviews of Pokemon Scarlet and Violet and The Oregon Trail are waiting for you to read. There’... | Read more »
‘OPUS: Echo of Starsong’ Interview: Port...
With OPUS: Echo of Starsong ($8.99) having finally launched on iOS after hitting PC and consoles, I had a chance to talk to Scott Chen who is the co-founder and executive producer of Sigono. In our chat, I touched on topics like game subscription... | Read more »
Best iPhone Game Updates: ‘Rush Rally 3’...
Hello everyone, and welcome to the week! It’s time once again for our look back at the noteworthy updates of the last seven days. As November breaths its last, the holiday season is right around the corner. That means we should start seeing more... | Read more »
‘Total Football’ is an Arcade-Style Socc...
GALA SPORTS recently launched its brand new soccer title, Total Football, and, true to its name, it is a pure arcade-style soccer game in the same vein as FIFA Mobile and PES Mobile. It also features official licensing from FIFPro and Manchester... | Read more »
Genshin Impact will recieve two new char...
HoYoverse has announced that Genshin Impacts version 3.3 will be arriving on December 7th. Titled All Senses Clear, All Existence Void, the update will bring two powerful new characters and a brand new card-based minigame. [Read more] | Read more »
‘Wreckfest’ Mobile Compared With Console...
HandyGames’ mobile version of Bugbear’s demolition derby-style racer Wreckfest ($9.99) released on iOS and Android recently, and we featured it as our Game of the Week. | Read more »
Black Friday Deals Here – The TouchArcad...
After taking a couple of weeks off we return on this glorious Black Friday with another episode of The TouchArcade Show. We get into a big discussion about virtual assistants like Alexa, Siri, and Google, and their place in the greater smarthome... | Read more »
TouchArcade Game of the Week: ‘Station 1...
I’m a big fan of Glitch Games and their unique brand of point-and-click adventure/escape room/puzzle games, and while they’re a tiny outfit and there’d typically be a couple years gap in-between their new releases, they were always worth the wait.... | Read more »
SwitchArcade Round-Up: ‘Super Lone Survi...
Hello gentle readers, and welcome to the SwitchArcade Round-Up for November 25th, 2022. Today we look at the remaining releases for the week, and I’ll be honest with you: it’s not a great assortment. Still, there are at least a couple of things... | Read more »

Price Scanner via

Cyber Monday: 24″ Apple M1 iMacs for $150 off...
Amazon has Apple’s 24″ M1 iMacs on Black Friday sale for $150 off MSRP. Their prices are currently the lowest available for new iMacs among the Apple retailers we track: – 24″ M1 iMacs (8-Core CPU/7-... Read more
Cyber Monday Sale: 25% off Apple MagSafe acce...
Apple retailers are offering MagSafe accessories for up to 25% off MSRP for Cyber Monday. Here are the best deals available, currently from Verizon and Amazon: (1) Verizon has Apple MagSafe Chargers... Read more
Cyber Monday Sale: Apple AirPods for up to $1...
Looking for Apple AirPods, AirPods Pro, or AirPods Max this Cyber Monday? Look no further than our Apple AirPods Price Tracker. We track prices from 20+ Apple retailers and update the tracker... Read more
Final day for Apple’s Black Friday/Cyber Mond...
CYBER MONDAY Apple’s four day Black Friday/Cyber Monday 2022 event is now live and will run from November 25, 2022 to November 28, 2022 (ends today!). Receive a free $100-$250 Apple Gift Card with... Read more
Cyber Monday: Apple 13″ M2 MacBook Airs for $...
Apple retailers have posted their Cyber Monday prices on 13″ MacBook Airs. Take up to $200 off MSRP on M2-powered Airs with these sales with prices starting at only $1049. Free shipping is available... Read more
The best Cyber Monday iPhone sale? This $500...
If you switch to Xfinity Mobile and open a new line of service, they will take $500 off the price of a new iPhone, no trade-in required. This is the best no trade-in Cyber Monday Apple iPhone 14 deal... Read more
Cyber Monday Sale: Apple 16″ MacBook Pros for...
Amazon is offering $500 off MSRP discounts on Apple 16″ MacBook Pros with M1 Pro CPUs as part of their Cyber Monday sale. Their prices are the lowest available for these models from any Apple... Read more
Cyber Monday Sale: Apple 14″ MacBook Pros for...
Amazon is offering $300-$500 off MSRP discounts on Apple 14-inch MacBook Pros with M1 Pro CPUs as part of their Cyber Monday sale. Their prices are the lowest available for these models from any... Read more
Cyber Monday Sale: Apple Watch Ultra for $60...
Amazon has Apple Watch Ultra models (Alpine Loop, Trail Loop, and Opean Bans) on sale for $60 off MSRP as part of their Cyber Monday sale, each including free shipping, reducing the price for an... Read more
Cyber Monday MacBook Sale: 13″ M1 Apple MacBo...
Amazon has Apple 13″ M1 MacBook Airs back on sale for $200 off MSRP, starting at only $799, for Cyber Monday 2022. Their prices are the lowest available for new MacBooks this Cyber Monday. Stock may... Read more

Jobs Board

*Apple* Electronic Repair Technician - PlanI...
…a highly motivated individual to join our Production Department as an Apple Electronic Repair Technician. The computer repair technician will diagnose, assemble, Read more
Product Manager II - *Apple* - DISH (United...
…you will be doing We seek an ambitious, data-driven thinker to assist the Apple Product Development team as our new Retail Wireless division continues to grow and Read more
Staff Engineer 5G Protocol, *Apple* - DISH...
…metrics. Essential Functions and Responsibilities for a Staff Engineer 5G protocol( Apple ) Knowledge of 5G and 4G/LTE protocols and system architectures Experience Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States ( - Apple Blossom Mall Read more
Omnichannel Associate - *Apple* Blossom Mal...
Omnichannel Associate - Apple Blossom Mall Location:Winchester, VA, United States ( - Apple Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.