Programming Multitasker 1.0
WHO THIS GUIDE IS FOR:his guide is written for people who have at least a little experience in programming in yBasic, and want to learn how to write Multitasker-compatible and Multitasker-enhanced programs, or just learn how Multitasker works.
If you’re just reading this, you may be wondering exactly what Multitasker does. Basically, Multitasker is a high-level environment that consists of the Multitasker applications plus the Multitasking manager. The basic structure looks like this.
Multitasking apps are actually combined with the multitasking manager at startup and then run as subroutines of the multitasking manager, which decides between which subroutine(out of two) to run, based on whether the given application is “active” or not.
For this reason, Multitasker apps will generally run more slowly than compiled or ordinary yBasic apps, which is something to be taken into consideration when d3signing programs.
Multitasker programs can also take advantage of special services offered by the multitasking manager, such as creating windows and using force feedback.
All Multitasker 1.0 programs follow this basic structure
This program is just a basic skeleton structure—it will not actually do anything. Still, it has all of the important elements of a multitasker program. These are the init, grun, and qrun subroutines.
INIT:The “init” subroutine contains commands to be run while the program is starting. Typically, this will be variable initializations, or setup procedures. The init subroutine is only run once.
GRUN:The grun subroutine contains commands that are to be run while the application is active(the user has switched to it). This subroutine generally contains commands for the user interface as well as data processing. THE GRUN SUBROUTINE IS NOT RUN WHEN THE APPLICATION IS RUNNING IN THE BACKGROUND
QRUN:The qrun subroutine contains code for operations that are to be performed in the background, i.e.loading data. It usually does not contain much, if any, UI stuff since another application is active when it is running.
The other part of the subroutine is the number after the “init” “grun” or “qrun”. This number is the application ID number, and it is necessary for applications to run correctly. The ID number can be from 1 to 10, and no other application can have the same ID. Note that this is a dynamic allocation, and if you have more than ten applications some can share ID numbers, but those two applications cannot be run simultaneously on the same device.
The other part of this is the file name. A multitasker program must be in a file called “#mmpx.bas”, where x is the ID number.
Now, suppose you’ve written a program and you want to port it to Multitasker. You figure out which parts you want to run when, and set it up according to the structure above. Then you run it andÖit doesn’t work. Maybe it generates a bizarre error, or maybe your device seems to hang or not do anything. In either case, there’s more to multitasker porting than just putting things in subroutines .
A common error is forgetting the use of “state” variables. Because your program is being run from the beginning many times a second, it is possible for it to keep repeating the same operations over and over again. Luckily, there is a solution to this:set a specific variable, calledsomething like’programstate” to 1 in the init subroutine, and then increment it every time the program completes a task. Then, use If-ENDIF statements to determine which task to do next(this method is implemented in the programs that come with Multitasker).
Another thing to be aware of is vriable names. Because Multitasker applications are basically assimilated into one large application during the loading phase of the multitasking manager, all of the variables are shared. This means that if two programs are using a variable with the same name. If one application modifies this ariable, it can interfere with the operation of the other program using the same variable, leading to erratic behavior. The solution to this is simple:suffix all variables you use in a program with the p-ogram’s ID number. This way, it is unlikely that program variables will conflict, since it is unlikely that application 2 will use a variable called “foobar5”, if this scheme is adhered to. Similarily, if you need to have multiple variables that all control similar functions, and thus have the same name(i.e.five different variables for five different FOR lops are called for1, for2, for3, etc) consider organizing them into an array(i.e.for(0), for(1), etc.). If this is impossible, then use other application specific names, such as “app1for3”.
A final note is the “refreshdata” variable. This is a variable which tells an application that it need to refresh the data it is displaying on the screen. Your applicaion only needs to pay attention to refreshdata if it is the active application, as the multitasking manager handles refreshing data displayed in windows, as long as the window arrays are not reset(more on this later).
If your program is active(running the grun subroutine) and “refreshdata” is equal to one, this means that your application will need to redraw its graphics. Oftentimes, this can be done with just the simple command at the beginning of the grun subroutine “if refreshdata=1 then cls”, before any state IF statements. However, some applications may also require specific parts of the UI to be redrawn in response to a refresh request.
USING ADVANCED FEATURES
In addition to simply allowing multiple programs to run at one time, Multitasker 1.0 also offers several advanced features to developers, which allow them to extend applications and increase the user-interface and functionality possibilities.
One of the most immediately noticed things in Multitasker 1.0 are windows. Creating a window is also very easy, a very basic window can be created simply with the command “winrequest(y)=1”, where y is the program’s ID number. This command will create an all-black window with no text and a size of zero(not very interesting). In order to create a window that actually does something useful, you need to specify some of these extra parameters:
winheight:window height in pixels(this excludes the top gray part)
winwidth:window width in pixels
wintxt1$:first line of text in the window
wintxt2$:second line of text in the window
wintxt3$:third line of text in the window
wintxt4$:fourth line of text in the window
wintxt5$:fith line of text in the window
wintitle$:Title that’s displayed in the gray area
winx:initial X position of the window(it may be moved by the user)
winy:initial Y position of the window(it may be moved by the user)
winr:RBG red value for the background color of the window
winb:RBG blue value for the background color of the window
wing:RBG green value for the background color of the window
okbutton:specifies wether to include an “OK” button
cancelbutton:specifies whether to include a “Cancel” button
closemywindow:set to 1 to close window
it is important to note that all of the parameters must be in the form of arrays, e.g. “wing(3)=200”(this sets the wing value for app 4 to 200). All of the parameters retain their settings until modified by the program, with the exception of the “closemywindow” and “winrequest” parameters, which are set back to zero after the window is opened or closed.
The other part of using windows is returning user inputs to the program. This is done by way of the the variables “cancelinput” and “okayinput), which are also set up as arrays in the same style as the parameters. For example, application 2 can check to see if the user has tapped the “OK” button in its’ window by checking the “okayinput(1)” variable. This variable will be 0 if the button has not been tapped, and 1 if it has been(the same is true for the cancelinput variable, but for the cancel button).
Another advanced feature in Multitasker 1.0 is the use of vibrating force feedback. Multitasker can produce tones through the internal speaker of a Palm OS 5 device that allow it to produce vibrations. The multitaskingmanager also allows for two kinds of vibration “quiet” and “noisy”. “quiet”, as the name suggess, does not produce much audible sound, but produces vibration. The “noisy” setting, on the other hand, produces a nosie that can best be described as “A stalling power tool”, but generates a more intense vibration. Both the “quiet” and the “noisy” modes are simply called as subroutines using the following commands
Another problem that Multitasker developers sometimes run into is the issue of their softeare abruptly shutting down, usually right in the middle of processing some data. The reason for this is called a “timeout”:each application is assigned an amount of time that it can dominate the CPU for before Multitasker decides that it is malfunctioning and terminates it. However, this behavior can also cause applications that need to use the CPU for long periods of time to quit unexpectedly.
The best solution to this is to simply not have your program se the CPU for so long at one time, perhaps bybreaking the processing up into several smaller bits. However, if this is impossible, then Multitasker can be instructed that your program needs a lnger-than-average timeout by oplacing the code “timeoutx=z” in the init subroutine, where x is the program’s ID number and Z is the timeout(in seconds).
Another similar issue is that of quitting an application. If a user wants to close your application, it is possible to put a “quit” button on the screen and have the application simply not do anything when it is run once the quit button is pressed. This is, however, not a very good way to do this, as it causes even closed applications to consume some resources. Instead, it is better to use the system “run” variable, which is structured as “runx=a”, where x is the program’s ID number and A is either 1(run this program) or 0(don’t run this program).
A thing to keep in mind is that when an application is “quit”, any variables that it has set will remain set, including window variables. This means that an applicationis quited and then restarted, all of the window parameters will be set to whatever they were last, before the user exited the program.
Quitting or launching an application is also not entirely under program control. A user can quit an application from the task manager, in which case the application is not notified that it will be shut down. If your application needs to perform an action, such as saving a file before it shuts down, set it to watch the “screen” variable and automatically save if it is equal to 0(this indicates that the user has entered the task manager and must be pt in the “qrun” section of the program’.
When something goes wrong
Computer programs pretty much inevitably malfunction in some way at some point, due to typos, incorrect command usage, or just bugs in the operating system. Adding an additional layer of complexity(the multitasking manager), also increases the chance that something will not work quite right.
The first thing to do when trying to fix a bug in a Multitasker program is to figure out if it’s your program’s fault. This can be challenging, as error line numbers usually don’t tell you much, as the line number may be inside the multitasking manager or another program(and who wants to count down 750 lines of code, anyways?)
The first thing to do therefore, is to change the filename of your program, create a skeleton program with the original filename, and then try running it again. If it runs, then it’s probably either an error within your program or a conflict with something else. The next thing to try in this case is MultiTester(available for download at “http://domoresoftware.tripod.com/multitester.html”), a small standalone program which is designed to troubleshoot Multitasker programs by emulating a Multitasker session but with only one application, allowing you to determine if the problem is within your program or resulting from an external conflict. However, MultiTester does not include a window manager.
If the problem turns out to be external, , check for likely culprits. Arrays with the dsame name that are dimensioned more than once can cause problems, as can attempts to use I/O media that are already in use by another application(e.g.two applications trying to open files for write at the same time). Try changing file accsess numbers and closing file or serial I/O before your program turns control over to the next program
If the problem results from an internal error, eg.g. a syntax error, the best way to find it is running it in MultiTester and figuring out the source of the problem by placing print “’ commands before and after any other commands that you think might be causin the error to occur. Then, count the number iof empty dialog boxes that the program generates in MultiTester before it crashes.