I describe the implementation of, and experience with, recording and playback of user actions during execution of application programs. All operator console applications have access to this facility as part of their runtime environment. It is used for program macros, safe operator training, and application tutorials. Various difficulties and capabilities inherent to this type of facility are also discussed.
+ Operated by the Universities Research Association, Inc. under contract with the U.S. Department of Energy.
This facility was originally conceived as a means to allow master applications to start up slave programs and have them perform a specific task. There is a long history of this functionality being utilized in the Fermilab control system. In the past, however, the slave applications had to be extensively modified to support this form of execution. Additional modifications to these programs were required each time new slave functionality was needed. When a new generation master application, referred to as a sequencer program, was created, the implementors decided a more extensible method was needed to control the slave applications. This facility had to be both available to all existing applications and easy to utilize by the person implementing the new functionality. The method chosen for this was to create a program recorder system. This immediately satisfied the second requirement. Anyone who knows how to perform the desired slave function can execute the application and "program" it to be utilized by the sequencer program. It still remained to satisfy the first requirement to make this available to all applications. At Fermilab, there are presently a few hundred different applications which, at first glance, would make this seem like a difficult task. However, all of these applications have at their core an infinite loop handling program events. There is a single function named 'intype' that supplies all programs with the events that determine their execution. It is possible to register callback functions with intype. This is the mechanism utilized to implement program recording. At application startup, the intype function calls a routine which determines if the user wishes to record this execution of the program. If so, a callback function is registered that will for the life of the program read the event information supplied by intype and store it in a buffer in dynamic memory. When the program is exited this buffer is saved into a file for future playback. The playback of a program recording, which is called a script, is basically a simple reversing of the recording process. When a playback is initiated, the buffer of recorded events is read in from its file and another callback function is registered with intype. This callback takes advantage of a useful feature of intype callbacks which allows them to modify the actual event data supplied by intype. The playback callback takes the information for the next event in the saved buffer and replaces the original intype event data with it. In this way the rest of the program should behave exactly as it did when the events were being supplied by the user. As a matter of fact, one can even record the playback of a previously created script. The actual implementation is a little more complicated in that repeated events are saved in a compressed format, but that is the basic mechanism.
The recording activity is always controlled by the user through a selection made just before executing the application. Playback, however, as stated earlier, must be controllable programmatically via a master program as well as manually by the user. This is done by passing a buffer of information to the program being initiated that contains the ASCII name of the script to be played, which is specified by the user at script creation time, and a playback speed. The playback speed is a float value between 0.0 and 1.0 inclusive. This parameter controls the time between playback of actual user events. A value of 1.0 results in playback at the same speed at which the recording was made. This would be used if you actually wanted to watch the events take place. A value of 0.0 eliminates all dead time between user events which accomplishes the playback in as short a time as possible. Any playback session, regardless of how it is initiated, can be terminated prematurely by the user by clicking the mouse button. A script termination dialog is then presented which allows the user to end the playback or to continue at the point it was interrupted.
Once the facility was created, it was apparent that it could also provide a means for training new operators in the use of an application, run displays for public tours, or simply show new program features. To enhance this mode of use, the ability to insert special events into the recording or script was added. If the "insert" key is pressed while the recording is in progress, a menu of special items is displayed to the user. Presently these items include the displaying of a GIF format image, displaying of a text file, or the insertion of a timed delay into the playback. Whether or not a special event is selected, the pressing of the "insert" key is not saved in the recording. With these special events one could create a script which displayed a picture of the author of the program followed by a thorough exhibition of the possible uses of the program interspersed with dialog windows of explanatory text.
Another possible use of program recording is to create macros which are simply a sequence of operations to accomplish a particular task. This exposes one of the problems with a facility such as this. Since it faithfully reproduces the events in a program without knowing anything specifically about that program, it suffers from history problems. For example, if the program contains global variables which affect how the program functions, the playback may have different results depending on how those variables are loaded. To address this situation to some degree, the recording can be made such that when it is played back it first restarts the application before proceeding. This, of course, initializes all global values at the cost of destroying other values which one might have desired to keep.
Another problem that has arisen with this system is one of maintenance. It is easy to continue creating scripts until one reaches the point that a program has so many of them that it is hard to determine at a glance which are really worth keeping. We are implementing a script database which will store descriptions of each script as well as its author and other miscellaneous identifying information. This should allow for responsible system maintenance.
When this facility was first made available, some people involved with machine operation were concerned that users would indiscriminately run scripts which would set devices or write to files. To help protect against this, a warning dialog is now displayed if the script about to be executed may set devices and/or write to files. Also, in addition to the special events mentioned earlier, events were added to allow enabling or disabling device settings and enabling or disabling file writes. By default, when a program recording is begun, both device setting and file writes are disabled.
A mechanism for editing scripts has been discussed At this time, however, none has been implemented. The process of recording a new script is far easier than any editing facility yet considered. This may change in the future if scripts greatly increase in length and complexity.
This facility has been very successful at solving the original problem of controlling slave applications. It has been less successful in its role as a training tool. This is due to the fact that it still takes a great deal of planning to create a useful, in-depth demo. A future which will demand much more from the machine operators should lead to a greater role for this use.
The author wishes to thank Tim Zingelman of Fermilab who collaborated with him to produce the program recording facility. Kevin Cahill and James Smedinghoff also provided a great deal of help and advice in this project.
[1] Hendricks, B. (1991). Overview of the Next Generation of Fermilab Collider Software, Proceedings of the International Conference on Accelerator and Large Experimental Physics Controls Systems, pp. 243-245