CanDo: An Interactive Authoring Tool, Playing Music and Handling Icons

by Randy Finch

In this installment I discuss the tools available in CanDo for handling icon files and playing music files. I wrote a program named YeOldeSongPlayer that makes use of these tools. It allows music files (Sound/Noise/ProTracker, Oktalizer, and MED) to be selected and entered into a list. The music files can be played, and the file list can be saved and loaded. This program operates on the Workbench. Its interface is shown in Figure 1. A print-out of the program is shown in Listing 1.

Overview of the Program

YeOldeSongPlayer's interface consists of one card named SongPlayer containing one list box object named SongList, one timer object named WaitForSongEnd, and five text buttons named Select, Load, Save, Play, and Next. The list box is used to display the list of selected music files. When a music file is selected within the list box, it begins to play.

The Select button is used to display the standard Amiga file requester (part of asl.library). Multiple files can be selected by holding down the SHIFT key while clicking on the filenames. Upon clicking the OK button in the requester, the selected filenames are inserted into the SongList list box.

The Save button is used to save the current list of music files to disk. The filename is obtained through the file requester. YeOldeSongPlayer is unusual in that the list is saved as part of an icon file using the ToolTypes feature of icon files. Only an icon file is saved. For example, the list might be saved to an icon file named MySongList.info. There will be no associated MySongList file as is normal. Of course, this can be confusing to some users and is not recommended. However, I use it here to illustrate the powerful tools available in CanDo for handling icon files.

The default tool for the icon files is set to SYS:YeOldeSongPlayer. Remember that while designing a program within CanDo, the deck file on disk is a CanDo project file. To convert this project file to a tool file, TheBinder or TheMultiBinder utility, included with CanDo, must be used to convert the project file to a stand-alone program, or tool file. This bound program must be in the main directory of the system disk for the default tool of the icon files to be correct. Alternatively, the default tool could be changed within the YeOldeSongPlayer deck.

Since the music list icon files have a default tool, they can be double-clicked to launch YeOldeSongPlayer which will insert the music file list associated with the icon file into the list box. Also, several music list icon files can be selected simultaneously by holding down the SHIFT key while selecting the icons. By either double-clicking the last selected icon or by double-clicking the YeOldeSongPlayer tool icon after selecting the last icon, YeOldeSongPlayer will begin execution. Each list of music files in all the selected icon files will be added in turn to the list box. This allows music filenames to be grouped by some criteria and then combined easily at a later time.

The Load button is used to load a music file list saved with the Save button. A file requester is used to obtain the filename. Only files with an extension of .info are displayed since all lists are saved as icon files.

The Play button starts playing the first music file in the current list. The WaitForSongEnd timer object checks every second to see if the song is still playing. When the song finishes, the next song in the list will begin. This will continue until the last song in the list has finished playing. At this point, playback quits. It can be restarted by pressing Play again or selecting a file in the list box.

The Next button will stop playing the current music file and begin playing the next one in the list. This is nice if you happen to include a song in the list that you despise.

Let's now look at the CanDo scripts in more detail.

The BeforeAttachment Script

This script executes when the SongPlayer card is first activated. It first initializes some variables that will be used later in the program and then sets the default directory to SYS: using the SetCurrentDirectory command.

An icon is created with the MakeIcon command. It has four parameters: buffer name, type of icon (TOOL or PROJECT), icon image file or buffer name, alternate image file or buffer name. The icon created is named SongPlayer (note that this is the same name as the card) and is a project icon. The first image is set to a brush file named SongPlayer1, and the alternate image is set to a brush file named SongPlayer2. Both brushes were created in Deluxe Paint. They are shown in Figure 2. SongPlayer1 will be the icon image seen on the Workbench screen when it is unselected. SongPlayer2 will be the icon image seen when it is selected (see Figure 1). The default tool for the SongPlayer icon is set to SYS:YeOldeSongPlayer using the SetDefaultTool command.

Two documents are created: Songs and FileList. The former is used to hold the list of music filenames; the latter is used to hold the names of the multiple icon files selected before executing YeOldeSongPlayer. The icon file list is inserted into the current document, FileList, with the command InsertStartingMessage. When a CanDo program is executed from the Workbench, this command inserts the names of all selected icon files. If the program is executed from the CLI, this command inserts all of the parameters following the filename on the command line. The InsertStartingMessage will only work properly after converting the CanDo project file to a tool using TheBinder or TheMultiBinder.

(Although not used in YeOldeSongPlayer, if you ever need to know whether a CanDo deck was started from the Workbench or the CLI, the system variable StartedFromWorkbench can be tested. If it is equal to TRUE, the program was started from the Workbench, otherwise it was started from the CLI. If a program is started from the CLI, the command line string will be returned in a system variable named TheCommandLine.)

After inserting the icon filenames into the FileList document, the cursor is moved to the top of the document. Each icon file, in turn, is loaded into a buffer named Temp using the LoadIcon command. The icon file's tool types list, which contains the names of music files (see Save button below), is inserted into the Songs document using the InsertToolTypeList command. Thus, if several music filenames have been grouped and saved as separate icon files, the groups can be combined very easily by selecting all of the icon files before executing YeOldeSongPlayer. Alternatively, the program can be executed from the CLI with multiple parameters as follows:

	YeOldeSongPlayer Songs1 Songs2 Songs3

This has the same effect as selecting the Songs1, Songs2, and Songs3 icons on the Workbench using the SHIFT key and then double-clicking the YeOldeSongPlayer icon.

To close out the BeforeAttachment script, the current working document is set to Songs since it is the only document that will be used in the rest of the program.

The Select Button

This button is used for selecting multiple music files to be added to the list box. When it is pressed, its OnRelease script performs several commands. First, the SetFileRequestMode command is used to set the multi-select mode and to specify that icon files should be rejected. Next, the SetFileRequestPattern command is used to set a pattern of #?, or all files. This information is used by the AskForFileName function. When the standard Amiga file requester appears, it will show all non-icon files and allow multiple files to be selected while depressing the SHIFT key (see Figure 3). The current directory and filename are passed to the requester via the variable File. When the Select button is pressed for the first time, File will be equal to NULL (set in BeforeAttachment). Therefore, the default directory of SYS: (also set in BeforeAttachment) will be used.

If the Cancel button is pressed on the file requester, then Files will be equal to NULL and no further action is taken. If the OK button is pressed, then Files will be a string containing all of the selected filenames separated by a line feed character (ASCII 10). In this case, the song currently playing is paused, the variable PlayFlag is set to FALSE, the Songs document is cleared, and the variable Files is typed into the document. Finally, the first filename is extracted from the Files variable using the GetWord function and assigned to File. This allows the path and filename of this file to be used as the default when the Select button is pressed the next time. The first filename must be extracted because the file requester gets confused if it is passed multiple filenames.

The Load and Save Buttons

These buttons are used for loading and saving a list of music files. Their OnRelease scripts are very similar. In each, the appropriate file requester modes are set, and the file pattern is set to #?.info. Thus, the file requester will display only icon files. REGULARMODE causes the file list in the requester to appear normally; SAVEFILEMODE causes the list to appear in inverse, giving the user visual feedback that a file is about to be saved rather than loaded. The variable SongsFile is used as the current path and filename for the requester. When the Load or Save button is pressed for the first time, this variable will be equal to NULL (set in BeforeAttachment). Therefore, the default directory of SYS: (also set in BeforeAttachment) will be used. The selected filename is assigned to the variable NewSongsFile if the OK button is pressed, a NULL is assigned to NewSongsFile if the Cancel button is pressed. If NewSongsFile is not equal to NULL, then its value is checked to see if the filename contained therein has an extension of .info. Several string functions are used in this determination: NumberOfChars, FindChars, and LowerCase.

In the case of the Load button, if the selected file is indeed an icon file (has an extension of .info), then several things occur. The song currently playing is paused, the variable PlayFlag is set to FALSE, the .info extension is stripped from the filename in NewSongsFile (using the GetChars string function) and the result is assigned to the variable SongsFile, the icon file is loaded into the Temp buffer (the LoadIcon command automatically appends .info to the filename), the Songs document is cleared, and the tool types of the icon in the Temp buffer are inserted into the document. In order for all of this to work properly, the selected icon file should be one that was saved using the Save button. Otherwise, an erroneous list or no list at all will appear in the list box.

In the case of the Save button, if the selected filename has an extension of .info, it is stripped off because the SaveIcon command, like LoadIcon, automatically adds this extension. The SetToolTypeList command moves the text in the Songs document to the tool types list in the SongPlayer icon (created in BeforeAttachment). Finally, the SaveIcon command saves the SongPlayer icon with the selected filename (variable SongsFile).

The Play and Next Buttons, the SongList List Box, and the WaitForSongEnd Timer

All four of these objects are very similar in that they all depend on the global routine PlayNextSong. When the Play button is pressed, the cursor is moved to the top of the Songs document and PlayNextSong is executed. When the Next button is pressed, the cursor is moved to the next line in the Songs document and PlayNextSong is executed. When the user clicks inside the SongList list box, the cursor automatically moves to the line selected. Therefore, it is only necessary to execute PlayNextSong.

The WaitForSongEnd object is an interval timer that, when active, executes its Occurred script every second. This script checks the current value of the system variable CurrentSongName. This variable is equal to NULL if no music file is currently playing, otherwise it will be equal to the name of the music file currently playing. When CurrentSongName is NULL, meaning that no song is currently playing, and PlayFlag is TRUE, meaning that one has been playing, then the cursor is moved down one line in the Songs document and PlayNextSong is executed. This is not a very good way to determine if a song has stopped playing. Unfortunately, there is no command to test directly when a song has finished playing. A tech support person at INOVAtronics said they are planning to add this feature in a future release.

The PlayNextSong Global Routine

This routine first checks to see if the WaitForSongEnd timer is currently active, or attached. This is done with the ObjectAttached function. If it is currently attached, it is detached. Next, the currently playing song is paused. The FileType function is used to determine if the file represented by the current line in the Songs document is of type Music. If it is not, the cursor is moved down a line and the next file is checked. When a file of type Music is found, it is played using the PlaySong command, PlayFlag is set to TRUE, and a delay of five seconds occurs before reattaching the WaitForSongEnd timer object. The delay allows time for the music file to be loaded before reactivating the timer. Five seconds should be sufficiently long for rather large music files to be loaded from a hard drive. However, this delay may need to be lengthened when loading large music files from a floppy drive. Finally, when the end of the Songs document is reached (TheLine equals NULL), PlayFlag is set to FALSE.

The Cool Down Period

Well, we have been at it for quite a while. It's time to enter the cool down period of this exercise. Be aware that YeOldeSongPlayer is a very basic program. Many enhancements could be made such as checking the file type before adding it to the list, allowing the order and content of the list to be modified, allowing lists to be concatenated from within the program, etc. There are also commands available such as SetSongVolume and SetSongTempo that could be used in conjunction with some extra buttons to adjust volume and tempo while a song is playing. Feel free to take this basic program and embellish it. I would like for you to send me a copy of the improved program. Mail it to the address below. See you next time.


Back to list of articles
Back to Randy Finch's Home Page
Last modified on April 1, 1996
Randy Finch at webmaster@rcfinch.com