- CAL gives us the chance to send information and data to the user and to the MIDI port.
Along with these output functions we will also discuss the "format" function
which converts variable data into text for sending to functions that places text in TRACK
VIEW screen fields (and thus into the sequence file).
- (message "text"
- This function places a message on the status bar at the bottom of the screen. It doesn't
interrupt the operation of the program, just displays the message. The message contents
can be text in quotes or variables that will display the values in the form of numbers or
any mixture of the two. There is an important thing to consider about sending messages to
the status bar. While a "forEachEvent" loop is running, CAL has exclusive access
to the status bar. However, outside this loop, anything CAL puts there can be overwritten
by a Cakewalk internal function message like letting you know that an autosave is going
on. Autosaves can happen during CAL programs. For that reason, you can't be assured the message will
be there long enough for the user to read it. Needless to say, after the CAL program ends
and supposing there are no autosaves, just pointing the mouse at a display field will
replace the message with the description of what the cursor is pointing at. If the pointer
happens to be over such a spot when CAL stops, any message will be immediately
overwritten. This aside, the message is a good way to let the user know where the program
is and that it is alive and running, less the user panic during a long loop and think the
system has locked up. There is a price to pay for this function; time. It takes longer to
run a CAL program if there is constant updating to the status bar. Consider this code
(message "Processing Event # " (index))
(if (so on and so on......
- CAL will be sending a new message to the screen every time the "forEachEvent"
starts a new pass. While this can be a great way of keeping the user transfixed on the
status bar as numbers flicker by at a rate too fast to read, It also slows down the system
by a fair amount. For small loops it can almost double the execution time of a program.
You must weigh the costs and benefits of providing such an ongoing tally message. Remember
to leave a space between closing quotes and variables because unlike some versions of
BASIC, CAL doesn't format the display of variables and text for you.
- (pause "text"
- This is similar to the "message" function and like it you can display any
combination of text and variable content. The difference is that "pause" halts
execution of the CAL program and displays a dialog box in the middle of the screen
containing the information the user provides in the function statement plus OK and CANCEL
buttons. The user must click OK or hit the ENTER key to acknowledge the "pause"
box before the program will continue. The user can also click the CANCEL button or hit the ESC key
and abort the CAL program completely. By the way, hitting the ESC key at any time in the
running of a CAL program will cause it to abort and exit. Besides displaying information
critical to the user's decision to continue the program or cancel, the "pause"
is a great troubleshooting tool for programmers. If a CAL program isn't acting quite right
or if you want to verify the operation of some part of a program, you can place
"pause" statements at key locations in the code to display the contents of some
important variables and see if things are running as planned. Note this example:
(if (> something somevalue)
(pause "Reached first test. somevalue = " somevalue)
(go on about your business.....
- Here a "pause" has been placed at the "else" part of an
"if" function to help verify if that function is being called. If it is, the
"pause" tells the programmer where the program currently is and what the current
value of variable "somevalue" is. After the programmer hits ENTER or clicks OK,
the program goes on as if nothing ever happened. By the way, there is a limit of 128
characters for a "pause" message, so if you have allot of information to give
out, it may require more than one "pause" box to deliver it.
- (format "text"
- Like the "message" and "pause" functions above, "format"
takes any combination of text and variable values and generates an ASCII text string that
can be passed to another function or assigned to a "string" variable. Take this
(int track 0)
(string name "No Note Has Been Found")
(if (== Event.Kind NOTE)
(= name (format "Note Number " Note.Key)
(TrackName name track)
- What we have done here is declare an integer variable that we will use for track numbers
and initialize it to 0 so it points to the first track (remember, we see tracks 1 through
256 and CAL sees them as tracks 0 through 255). Next we declare a string variable and
initialize it to a default text string. Next we enter a "forEachEvent" loop and
our "if" function filters out anything except notes. For each note we find, we
use format to convert "Note.Key" into a number and combine it with the text
string in quotes. The result is assigned to the string variable "name" and using
the "TrackName" function, we place this text in the on-screen NAME field for
track number "track". Now we increment "track" so that upon the next
occurrence of a note it will point to the next track and we loop again. When the program
stops, aside whatever else the program containing this fragment does, it will have named
tracks for each note in the selected part of the sequence. If you wanted to eliminate the
"track" variable all together, you could replace the first two statements after
the "if" with this single statement:
- (TrackName (format "Note Number " Note.Key) track)
- As a part of this program, you would also likely end up cutting out all of the notes of
each pitch and pasting them into the appropriately named tracks. This is useful with
percussion tracks where it's convenient to separate each percussion instrument onto its
own track so it can be manipulated independently.
- (sendMIDI port
channel kind data1 data2)
- You can send a MIDI event during a CAL program with this function. Use "port"
as the port number you want to send over. If "port" is set to -1, the function
will send the message through all ports. The "chan" variable is the channel
number and -1 will set the function to send over all channels. The "kind"
constant is one of the recognized event types such as NOTE or CONTROL just like with the
"insert" function. Use "data1" and "data2" for the
information to be sent. Not all event kinds use both data bytes, and you must use the
proper formatting of the data bytes for the event in question. Remember, MIDI data bytes
must be between 0 and 127 except for type SYSX (system exclusive message). The SYSX
message must be formatted by sending the number 240 for "data1" followed by
whatever data is to be sent and then ending with the number 247 as the last byte. Check
your synth MIDI implementation specs for details on how to use system exclusive messages
with your instrument.