1.2 Apple EventsAppleScript and scriptable programs communicate with each other via Apple events or internal, invisible messages. This section provides an overview of how Apple events are implemented with AppleScript. As this information goes beyond basic script development, some readers may choose to jump ahead to the book's language-reference sections, do some scripting, and then revisit this section at another time. 1.2.1 OSAThe Open Scripting Architecture, which has been present on the Mac since the early 1990s, is Apple Computer's mechanism for making interapplication communication available to a spectrum of scripting languages. AppleScript is the OSA language that Apple provides, but there are other OSA-compliant languages, including UserLand Frontier and JavaScript.[2]
OSA accomplishes this "the-more-the-merrier" approach to scripting systems by using Apple events as the unifying technology. The situation is similar to Open Database Connectivity (ODBC) on the Windows platform, where any client application can talk to different database management systems using ODBC as a common conduit (as long as ODBC driver software exists for that particular database). In terms of OSA, the conduit (on Mac OS 9) is a scripting component that can convert whatever scripting language is used (AppleScript or JavaScript) into one or more properly constructed Apple events. Figure 1-3 shows the same Apple event being sent to an application in two different scripting languages. Figure 1-3. OSA scripting tools send Apple eventsBefore AppleScripts or other scripting languages can be compiled and run, their corresponding extension files have to be installed (the AppleScript extension is included in an OS 9 installation) and then loaded into the computer's memory. The AppleScript extension or component is depicted in Figure 1-3. 1.2.2 Apple Event RegistryAlong with scripting components, another important OSA element is the Apple Event Registry. The Registry is an Apple Computer-maintained database that maps all of the Apple events that the Mac OS standard software uses to a corresponding English-language command. This means that the activate AppleScript command is mapped to an activate Apple event, quit is mapped to a quit Apple event, and so on. You can use the Registry to discover the Apple event codes that are used by the Mac's standard software (such as the Appearance control panel, the ColorSync extension, or Sherlock 2). Section 1.2.4 describes what these codes are.
To make them easier to understand and incorporate into applications, Apple events are logically grouped into suites or categories, such as the Database Suite, the Standard Suite, and the Text Suite. All Mac applications are required to support four Standard Suite events (open, print, quit, and run; this was the "Required Suite" prior to AppleScript 1.3). This does not mean that all Mac programs do support these events; software developers don't go to jail if they have not implemented these Apple events in their programs. However, this does mean that the vast majority of applications will reliably quit if, for example, your script sends them a quit Apple event. Applications and scripting additions can (and usually do) define their own Apple events and corresponding human-language commands. For example, the BBEdit text editor supports a subset of the Standard Suite of Apple events that you can look up in the Registry database. BBEdit also contains a set of events and classes known as the BBEdit Suite, which is unique to BBEdit. Table 1-1 shows the Standard Suite Apple events and Apple event classes that BBEdit 5.1 supports. It also shows the Apple events and Apple event classes that are listed in the BBEdit Suite. (Section 1.2.6 describes Apple event classes in more detail.)
1.2.3 Client/ServerThe application or applet that initiates an exchange of Apple events is called the client application. The client requests the help of the server ("do something for me!"). The client's Apple event(s) may request data (e.g., text, database records) or just a sequence of actions that the server should take ("Open a file and send me the paragraph that begins with 'Top-secret information.'"). The client can also be thought of as the Apple event "source," and the server can be thought of as a "target." An application can be both an Apple-event client and a target (if a client receives a reply Apple event, then it's the target of that event). A machine can send up to about 2,000 Apple events per second (and can be as pokey as about 5 per second). This speed depends on factors such as how quickly the target application can process the Apple event(s).
Let's drill down further into Apple events. Section 1.2.4 shows you what an Apple event looks like at the system level, using the sleep Apple event, a Finder command, as an example. 1.2.4 Inside an Apple EventHere's how it works when Script Editor compiles and executes the following code, which comprises a complete compilable script: tell application "Finder" to sleep This is what happens:
Here is an explanation of the structure behind the Apple event in Figure 1-4. Every Apple event is comprised of unique four-character codes that represent the:
The event class represents a grouping of similar Apple events. The event id uniquely identifies the Apple event. The target address is a complex data structure that could contain the application's creator code or its Process Serial Number (PSN) or another piece of identifying information. For example, the sleep Apple event has event class 'fndr' and event id 'slep'. Table 1-2 contains the event classes and event ids for the Standard Suite in the Apple Event Registry. Apple events often get reorganized within different suites when Apple updates its Registry.
Most of the time, however, a scripter does not have to deal with event classes and event ids, just their AppleScript language equivalents. Apple events specify the target programs that should receive the Apple event. Otherwise, your script would cause an execution or runtime error, because the operating system does not know where the Apple event is supposed to go. The common way to specify the target programs for an Apple event in AppleScript is to use a code such as in Example 1-2. You enclose the Apple events you will send to a program within the tell block, as in Example 1-2, which sends a quit Apple event to "FileMaker Pro". Example 1-2. A Script Targeting FileMaker Protell application "FileMaker Pro" quit end tell The value of the application signature attribute in Figure 1-4 is also a four-character code ('MACS' for the Finder), just like the event class and event id. You might recognize this code as the Finder's creator code.
1.2.5 Apple Event ParametersSometimes a lone Apple event like quit or activate will do the trick in a script. At other times, Apple events have to specify Apple event parameters. These are the data the receiver of the Apple event needs to carry out the Apple event's instructions. For instance, if the Example 1-3 script did not include the parameter: file "mydocument" then the OS 9 Finder would return an error, because its open Apple event requires a reference to the object(s) to open. Example 1-3. A Finder open Commandtell application "Finder" (*open is the command; file "mydocument" is the parameter *) open file "mydocument" end tell
Figure 1-5 illustrates the Finder's open Apple event with the reference to the mydocument file. Figure 1-5. The Finder's open Apple eventApple event parameters can include standard data types (e.g., integer or string) or references to Apple event objects, such as a document file. Apple event objects are the items or "nouns" (e.g., a file, a folder, a database record) that some scripts interact with. See Section 1.2.6 for further explanation on handling objects in your scripts. An Apple event can have more than one required or optional parameter. In another example, if you want your script to tell FileMaker Pro to create a new row in a database, then create is the Apple event (followed by the required keyword new). The create Apple event requires a parameter such as a record object (as in a database record or row). Otherwise, how would the database program know what you wanted to create? The code in Example 1-4 opens a database file and then creates a new record with empty fields. Example 1-4. Getting FileMaker to Create a New Database Rowtell application "FileMaker Pro" activate --brings the target application to the front open file "startupdisk:fm databases:myDB.fm4" create new record - "record" is the parameter end tell Example 1-4 could use the create command's optional with data parameter to fill the new row with data, thus creating a complete database record. 1.2.6 Apple Event Classes and ObjectsYou have read about Apple events, which are action words or verbs (activate, delete). Apple event classes (and the objects that are based on those classes) are the nouns that your script might want to manipulate in some manner (see Table 1-1). Example 1-2 told the Finder to open a file object (basically, a file on the desktop). Objects are the data or "things" that you are interested in querying or changing when you send an Apple event to a program. For example, a script that controls a database program usually deals with database, field, record, or cell objects. An AppleScript that sends commands to a text editor works with character, word, paragraph, and document objects. These Apple event objects are based on classes or blueprints, such as the file class or the database class. Table 1-3 shows some of the Apple event classes from the Apple Event Registry. The operating system represents these classes internally as four-character codes.
A class is a blueprint or data type for a noun or object that you can manipulate with a script. When an architect creates a blueprint for a structure, all the homes that are subsequently built off of the blueprint are the offspring of her original design. The real wooden, brick, or metallic homes are "instances" (in object-oriented parlance) or objects of the blueprint or class. The architect creates a home class in her blueprint, then the builders generate real home objects based on the original class. For example, the BBEdit text editor defines a word class, which is a bunch of characters that are unbroken by a space, tab, or new-line character (e.g., "apple"). The five characters that make up the word (a,p,p,l,e) are all objects based on the BBEdit character class. So a word object constitutes a group of character objects. If you grouped together several separate character objects they might look like ("a", "p", "p", "l", "e"). For example, when you get the Finder to open a folder with a phrase like: open folder "my_folder" then you are telling the Finder to open the folder object (based on the folder class) whose name is "my_folder." This line of code will specifically create a Finder window showing the contents of the folder called "my_folder." It is always important to describe an Apple event object in your script by its containment hierarchy, which is an exact specification of where an application like the Finder can find the object. Apple event objects are located in a similar manner to taking apart one of those wooden Russian dolls, where the dolls get smaller and smaller until you finally locate the last solid peanut-shaped doll inside of all the bigger ones. In other words, if you wanted to get information about the sender of the first message in your Outlook Express inbox folder, then you couldn't just tell Outlook to: get the sender of the first message because the emailer would not know where to look (i.e., in the "inbox" folder) for the email message. Consider Example 1-5, which incompletely describes the containment hierarchy for a file (assuming that the file is not located on the desktop). Example 1-5. A File-Access Script That Causes an Errortell application "Finder" open file "taxes2000" end tell The Finder cannot find this file because the script does not give a complete container reference, as in: open file "taxes2000" of folder "Taxes" of startup disk The script will therefore produce a dialog box reporting an error if it is run. AppleScript has a number of ways to express containment relationships. file "taxes2000" of folder "Taxes" of startup disk (an "inside-out" reference). This is like describing the smallest Russian doll as "the tiny doll inside the slightly bigger doll that is contained by all the larger dolls." Or, you can use a possessive form such as: startup disk's (folder "Taxes"'s file "taxes2000") Using the possessive style with long container references like this one is usually less readable than the inside-out method. 1.2.7 Elements and PropertiesTwo other very important characteristics of Apple event objects are elements and properties. The class that these objects are based on defines the object's elements and properties. An object has zero or more of its defined elements, and exactly one each of its properties. For example, SoundJam™ MP, a digital music player and encoder, defines a playlist window class. These objects are windows that contain lists of audio tracks that can play on the computer. Figure 1-6 shows the definition of the playlist window class from SoundJam's dictionary. (Chapter 2 explains a program's dictionary, which can be viewed by using Script Editor's File Open Dictionary menu command.) A playlist window object has three elements: track, file track, and URL track. Further, playlist windows have a modified property (a true or false value depending on whether the window was modified since it was last saved). playlist windows also inherit several properties from SoundJam™ MP's window class. So a playlist window object can contain zero or more "track" elements, but it only has exactly one "modified" property value. Figure 1-6. playlist window's elements/propertiesRest assured that it is easy to grab the values of elements and properties in AppleScript. You can use syntax such as: tell app "SoundJam™ MP" to get first file track of first playlist window This code sends SoundJam™ a get Apple event requesting a reference to an element, such as the first file track (an MP3 audio file) in the foremost playlist window that you see when SoundJam™ MP is open. The return value looks like: 'file track id 4 of playlist window id 5 of application "SoundJam™ MP"' Once your script gets a reference to a track, it can then command SoundJam™ MP to play it with (you guessed it) the play Apple event that SoundJam™ MP defines. Our introduction to Apple events concludes with a description of the all-important application class, which is the "king of the objects" in a scriptable program. The program that you script, such as application "SoundJam™ MP," is actually an object itself, an "instance" of the SoundJam™ MP application class. 1.2.8 Application ClassMany scriptable applications define an application class, which is the gem to study if you want to automate that program. Your quickest route to the application class is its description in the program's dictionary. We mentioned before that Mac programs can expose an object model to scripting components like AppleScript. An object model is a software abstraction, usually in tree-like form, showing the Apple event objects and Apple events that you can use with a program. The application class is the root or top-level class in the program's object model. An Apple-event object model shows the application class and all of its elements and properties (if it has any defined elements). Figure 1-7 shows a simple object model for Sherlock 2, the Mac's fancy Find program. Sherlock 2 has three properties and contains zero or more channel elements. (I am sticking to the strict definition of an object's elements, which is that an object can have zero or more of them. In reality, Sherlock 2 always has at least one defined channel, which is the domain that it is searching.) channel elements are themselves objects with their own properties: "all search sites" and "name" (e.g., the name of one channel is "Internet"). When in doubt about how to script a program, always use the program's dictionary to examine its application class. The elements and properties of the application class are the things that you will be able to control and derive values from with your AppleScripts. If you are on friendly terms with an illustration tool, then it helps to sketch out an object model of a program you are trying to script. Figure 1-7. Sherlock 2's application class |