Visual Basic Expert SolutionsChapter 15Multimedia in ActionBy Brian Blackman |
The Media Control Interface (MCI) gives you a way of delivering and composing multimedia content using a simple and easy to understand interface to control multimedia devices. The Media Control Interface enables the developer to control devices using a uniform and simple syntax without specific, low-level knowledge of the device. This chapter will focus on the real-world practice of the Media Control Interface concepts.
There are many devices for composing and creating multimedia content. These devices can be very complex and expensive. The software that drives the devices to create the content strains simple computer resources. You must understand that creating multimedia content and viewing that content takes two different sets of requirements. Creating the content can take much more horsepower than the personal computer that meets the MPC requirements. The MPC requirements are for the viewing and using of multimedia content. This requires far less computer resources than the creation of multimedia content.
In this chapter, you will learn the following:
Since the Multimedia MCI control is not one of the default controls
listed in your Toolbox, you'll need to add it to your project. To add a
custom control to your project choose Tools, Custom Controls.
In the Custom Controls dialog box click on the check box next to the custom
control you want to add to the project. Figure 15.1 indicates that the
Microsoft Multimedia Control has been added to the project.
Fig. 15.1 The Multimedia MCI control is not added to your environment by default.
When the custom control has been added, you will see the Toolbox icon shown in figure 15.2.
Fig. 15.2 The Multimedia MCI Control Toolbox icon appears after you add the custom control.
After selecting the Multimedia MCI control and adding it to a form, you will see a button bar similar to that of a tape recorder (see fig. 15.3).
Fig. 15.3 The Multimedia MCI control default button bar contains most of the functions you'll need.
The Multimedia MCI control manages the playing and recording of multimedia files on the following MCI devices:
For a detail listing of all the properties and events for the Multimedia MCI control, search for "Multimedia MCI control" in the Visual Basic Help file. Many of the properties listed are limited in relevance to the device that is being controlled. For example, a CD-ROM is a read-only media, therefore any properties relating to recording are not relevant. Of special note are the properties DeviceType, AutoEnable, hWndDisplay, Mode, Notify, Wait, and the events Done and StatusUpDate. The use of these properties and events in the sample application provide specific examples of the implementation details.
The simplicity of the Multimedia MCI control is exemplified in the DeviceType property, which specifies which device will be controlled. Through the use of string specifiers, you set this property to the device type (see Table 15.1).
Table 15.1 Table 15.1 Device Types for the DeviceType Property
Device Type | Description |
AVIVideo | AVI player |
CDaudio | CD Audio |
DAT | Digital Audio Tape player |
DigitalVideo | Digital video |
MMMovie | Multimedia movie player |
Other | Undefined device |
Overlay | Analog video in a window |
Scanner | Image scanning device |
Sequencer | MIDI sequencer |
VCR | Videotape recorder/player |
Videodisc | Videodisc player |
WaveAudio | WAV file player |
Note: The Command, hWndDisplay, Mode, Notify, and Wait properties are available only at runtime. Hence you set these properties in your code.
AutoEnable allows the MCI control to detect and enable the appropriate buttons on the control. While this is the default implementation, there are circumstances where you want this disabled, such as when you want to prevent the user from performing an action with the media until the application enables the function. The buttons are enabled and disabled individually.
The Command property is available only at runtime and setting this property immediately executes the command. You set the property using a string command. This demonstrates the simplicity of MCI and the Multimedia MCI control. You simply set the property to commands such as: Open, Close, Play, Pause, Stop, and Eject.
The hWndDisplay property sets and reads the playback window handle to allow the Multimedia Control Interface to redirect output from a default window (handle of zero) to the window you specify. You choose whether to use your own window or let MCI create a stage window. To get the handle of a form use then use the control's SetFocus method to set the focus to the control and then call the Windows GetFocus API to obtain the handle.
Mode allows the application to determine what the MCI device is doing. By reading the Mode property, your application can determine the correct operations to perform. The Mode status codes appear in Table 15.2:
Table 15.2
Table 15.2 Mode Status Codes
Code | Description | Constant |
524 | Device is not open | mciModeNotOpen |
525 | Device is stopped | mciModeStop |
526 | Device is playing the media | mciModePlay |
527 | Device is recording on to the media | mciModeRecord |
528 | Device is seeking over the media | mciModeSeek |
529 | Device is paused | mciModePause |
530 | Device is ready for MCI commands | mciModeReady |
Notify enables the device to send messages back to your application when a command has finished. By setting this property to True, the device will trigger the Done event when the current command has completed.
Wait allows your application to protect the device from further input until the current operation is complete. This is useful in an application that controls a VCR. For example, your Visual Basic application could require that after the playing of the video the device would not allow the tape to be ejected until the tape was rewound.
The Done event allows your application to handle information that is returned after a command is sent to the device with the Notify property set. The Notify values are 1 – Successful, 2 – Superseded, 3 – Aborted, and 4 – Failure. The constants are 1 – mciNotifySuccessful, 2 – mciNotifySuperseded, 3 – mciNotifyAborted, and 4 – mciNotifyFailure.
UpdateInterval triggers the StatusUpdate event. When the UpdateInterval time elapses, the application can read the newest statistics about the device. Using these features, you could display the current elapsed time of a media playback or recording.
The CD Jammer application is available on the book's accompanying CD-ROM. You'll find two versions; a 16- and 32-bit named CDJAM16.EXE and CDJAM32.EXE, respectively. For best performance simply copy the executable and CDJAMMER.AVI files to a directory on your hard drive. Then place an audio CD in your CD-ROM drive and run either version of this application.
Note: To run any of the Visual Basic applications on the CD-ROM you need to copy the VB40016.DLL and VB40032.DLL to your Windows, Windows 95, or Windows NT system directory. You can find these DLLs in the Chapter 15 directory on the CD-ROM.
The CD Jammer application was born out of a sense that the shareware versions of CD players were too expensive for the functionality that they provided, and the applications did not begin to explore the potential that was available for a Windows-based audio CD player. So the first versions of CD Jammer, which were written in Visual Basic 3, were released as freeware with the ability to play audio CDs. As the application progressed, other features began to appear, such as the ability to create customized play lists, shuffled play lists, and a database of the user's CD collection. The code from the freeware version of CD Jammer was used to create the examples in this chapter and the application that is on the CD-ROM.
As figure 15.4 shows, the main CD Jammer screen is comprised of a group of buttons that controls the functions of the CD player and it includes an LED-style track and time display.
Caution: The design of the main form requires at least a 256-color display. With most multimedia machines, this is fairly standard. On machines with displays that are less than 256 colors, the palette will dither some colors and may cause some odd colors to appear.
In CD Jammer, I chose not to use the Multimedia MCI control and used my own buttons. These buttons are grouped differently from the Multimedia MCI control buttons. This was done largely for aesthetic reasons. By grouping the controls differently and adding new icons, the application gets a fresh look and feel.
Caution: The code in this chapter only works if you have only one CD-ROM. It will not work if you have more than one CD-ROM connected to your computer. If there is more than one CD-ROM, the application makes no attempt to distinguish between the two or more CD-ROM devices. It is assumed that the majority of users of this application have one CD-ROM. Yet, now we have an opportunity to upgrade the feature set once again or to leave this as an exercise for the reader in MCI development!
Listing 15.1 shows the code used to program the new Play Button control.
Listing 15.1 CDJAMMER.FRM—The Play Button Control
Note: In Visual Basic 4, you use the constant vbNullString to pass a Null pointer to the Windows API. This is improved over the handling of passing nulls to Dynamic Link Libraries in previous versions of Visual Basic.
You may have noticed the reference to the function mciSendString. This is the multimedia "heart" of this application. The mciSendString commands provide all of the functionality to control and query the device's operation. This function demonstrates another method for creating multimedia controlling applications. mciSendString is a Windows API function and serves us well. By using this function we don't have to include the OLE Multimedia MCI custom control extension and thereby reduce the size of our application and number of redistributable files.
Windows API functions are declared in the Declarations section of the form; they must be declared Private. Listing 15.2 indicates the declaration of the 16-bit mciSendString and the 32-bit mciSendStringA functions, which can return error codes to your application. You can choose whether you want to handle and report these errors. The use of the alias feature gives us a way to use only one function name in our code instead of two function calls surrounded with conditional compilation statements.
Listing 15.2 CDJAMMER.FRM—Declaring the Multimedia Control Interaction Functions
While there isn't much to the functions declared above, they are responsible for one of the ways for interaction that CD Jammer (or any application) has with the multimedia devices. Since this code is responsible for the core functionality of the application, it is useful to understand how to communicate with the multimedia devices which it controls.
As discussed in Chapter 14, "Media Control Interface," the MCI command string is an extremely useful way to easily control multimedia devices and files. Programming from within Visual Basic requires little preparation or understanding of the strings that can be passed into the multimedia DLL. You have only one MCI API to call, mciSendString, with which you pass your string commands and these string commands are simple and self explanatory.
In addition to the declaration functions shown above, the buffers for the messages returned from the DLL must be created. In Visual Basic, a return buffer can be built using the String variable type. The following function indicates how a buffer of 1024 bytes or 1K can be created:
The following is an example of using the ReturnString in the mciSendString command function:
This would effectively send the open command to the CD audio device. The additional functionality of the ReturnString variable is not evident unless your application reads the return information in the buffer. Issuing an "open the CD device" type of command does not really yield much useful information from the ReturnString other than device status, but other commands pass interesting information such as the device's name and model number. The following function queries the CD audio device for information and then displays the returned information in a message box.
Note: For those of you familiar with 16-bit MCI development you will note the absence of the use of mciExecute(). This is a popular 16-bit MCI API, however, there is no mciExecute() in Win32.
Track playback was also enhanced through the use of shuffle play, custom shuffle, and custom play lists. The shuffle play feature basically randomizes the order of the songs to be played from the CD. Listing 15.3 shows the code used to generate the randomized play list for the shuffle play feature.
Listing 15.3 CDJAMMER.FRM—The Shuffle Play Feature
Note: For much of the code in this chapter you cannot just type in the code and compile. Most of the code contains interdependencies with other code in the project. If you want to type this code in yourself use the project on the CD-ROM.
The custom shuffle play feature allows the user to select individual songs to be played in a particular order, and allow the songs to be heard more than once if desired. With custom shuffle play, not all songs need be played. A selection of one song played three times in a row is an example of a custom shuffle play list.
The custom play list allows the user to create custom shuffle play lists and save them. This allows the user to create up to 99 different songs sequences for a particular CD. While this may be excessive for most users, you may modify the code in the database saving function to create as many play lists as you think are necessary.
The database feature allows the user to catalog his CD collection while he plays his CDs. Loading a new disc allows the user to begin the cataloging procedure. He may add information on the album title, the artist, and the titles of each of the songs on that CD. This database does not use the built-in Access database engine for the following two reasons:
The basic structure of the database file is that of comma-delimited, end-of-line terminated records. The following shows example data that you would find in a file created by the CD Jammer database engine"
The CD Jammer application is primarily an audio CD player. However, several features were added to demonstrate the true meaning of multimedia. For example, the application handles and catalogs text data for the audio CD such as artist, title, and song. This lets you build a comprehensive database of your CD collection. In addition to playing and cataloging the audio CD, the application also plays a Video for Windows AVI file and uses a LCD type display. The playing of the AVI file makes for a unique and great splash screen. The LCD display provides familiar application feedback to the user
The rest of this chapter will focus on the code and the design of these features to demonstrate how multimedia features interact within an application.
One of the first features added was the ability to automatically recognize the CD that the user had inserted into the CD-ROM player. This feature ranks highly for its "neat-o" effect. While it is fairly simple to accomplish, it provides a great selling point. An application can make use of this feature for audio CDs like the sample program or, in the case of a CD-ROM data vendor, it can check a data CD-ROM to verify that it's the distribution version that the application is expecting.
There are tracks on an audio CD that represent songs on an album. These songs have specific lengths that can be used to identify the particular CD by comparing the sequence of track times for a given number of tracks.
What happens if the first couple of tracks for two different albums coincidentally have the same lengths? Well, it may be possible for two or more albums to meet this criteria, but several factors weigh against it. First, a typical user's collection size will be a sufficiently small sample of all audio CDs in existence. This significantly decreases the chances that a user has two albums that register as the same album. Second, the time increments used to measure a track's length are very small. Table 15.3 illustrates how the first two tracks of two albums may appear to match, but in reality, they are different.
Table 15.3
Table 15.3 Track Length Comparison
Album Title | Track Lengths in Minutes and Seconds | Track Lengths in Milliseconds |
Herby's Greatest Hits | Track 1 – 3:24 | Track 1 – 204020 |
Track 2 – 4:18 | Track 2 – 257946 | |
Wanda's Tunes for | Track 1 – 3:24 | Track 1 – 203997 |
Tomorrow | Track 2 – 4:18 | Track 2 – 258094 |
Notice that the first track has a time of 3 minutes 24 seconds for both albums, but as the time format changes to a more precise measurement, the difference becomes apparent. Obviously, it would be far more difficult for an album to register incorrectly when track lengths in milliseconds are compared.
There is a particular event that would invalidate this type of comparison. It would be the case that the disc contains only one track that extends to the end of the media. An audio CD might not have this type of configuration but a data CD could certainly fulfill the requirements. In this scenario, an additional check mechanism should be instituted, such as a checking the date of the first file in the root directory of the CD.
Using a CD's recorded length, in milliseconds, can also be a fairly accurate identification routine. The Track Sequence method records the length of each song or track. The Disc by Length method measures the total playing time of the CD. Just like the Track Sequence method, this identification process makes the assumption that a user will have a small enough sample of available CDs to presume that each CD owned will have a unique amount of information recorded on it.
Again, this identification routine has the same drawbacks about full media as the Track Sequence method. However, in general, either of these processes should work well when implementing an automatic disc identification routine in your application.
The multimedia explosion is being fueled by the availability of full-motion video. To demonstrate this type of functionality, CD Jammer was designed with an introduction screen, or splash screen, which plays an AVI video file. Figure 15.5 shows a still image of the splash screen.
Fig. 15.5 A still shot of CD Jammer's splash screen video shows a CD-ROM spinning.
A great deal of time and effort went into designing and creating this video file. If you have never experimented with animation, ray-tracing, or video files, let me warn you that it is addictive. A good portion of a week was used to create the two-second animation that is the splash screen for CD Jammer. It would have taken much longer if I had not been as familiar with the POV-ray tracing application. While you are able to create stunning three-dimensional graphics, you need a lot of patience and a good creative touch.
Caution: It cannot be stressed strongly enough that multimedia applications will take much longer to develop than other types of applications. There is not much difference in the difficulty of coding the application, but there is a huge time factor for producing the "perfect" bitmaps, icons, video files, animation sequences, and audio files that most programmers have never encountered. Again, unless you start out with your eyes open, you will be disappointed with your development times.
Note: Unfortunately for many of us, we don't possess a lot of patience nor any creativity when it comes to graphic arts. However, there are many tools available, such as Autodesk's 3D-Studio and others, that make developing high-quality, ray-traced artwork and animation much easier.
To incorporate the AVI video file, the application must be able to verify the existence of special drivers. Microsoft's Video for Windows driver or some other manufacturer's driver capable of AVI playback must be installed on the user's PC to view the file. If your application will be distributed to the masses as a shareware program, then it is wise to specify that the Video for Windows drivers must be installed on the user's PC before she installs your application. Yet, with Windows 95 and Windows NT, Video for Windows is part of the normal installation and your users will already have the driver.
The code to display the AVI file in the splash screen window is detailed in Listing 15.4. This subroutine is called from the form's Form_Load event.
Listing 15.4 CDJAMMER.FRM—AVI Splash Screen Code
Note that this procedure has the benefit of error checking. While not used throughout the sample application's code it is added in this procedure for the reader's benefit as a demonstration on how to accomplish error checking using the MCI APIs. The call to the procedure GetMCIError() in the label Err_ABoutBox checks the error and reports it to the user in a message box. The GetMCIError() procedure is in the module GLOBAL.BAS.
While this is not the optimal method of handling the error, it does present to you, the programmer, the way of getting the MCI error. From that point you choose whether you want to handle the error, report the error to the user, or ignore it completely.
Also note that during the actual playback of the file, the status of the device is queried through a While loop. This is done because the application is not using the Multimedia Control Interface custom control, but is using direct calls to the multimedia DLL. Listing 15.5 shows example code that would be used to accomplish the same thing if you were using the Multimedia MCI control.
Listing 15.5 Playing the AVI File through the Custom Control
Either way that you choose to implement this functionality, the sequence of events is similar. Follow these steps to play a generic multimedia file:
1. Select the file to play.
2. Open the multimedia device that will play the file.
3. Begin playing the file.
4. Wait for the file to end its playback.
5. Close the device.
The last step of closing the device is very important. If your application does not close the multimedia device that closes the file that was being played, the next time that the application returns to use that device or file, it will be in use and unavailable.
Note: The exception to this rule is the CD-Audio device. Typically, the interaction with the user requires that the device is open to switch tracks, begin and end playback, and eject the media.
The next section discusses another form of multimedia file playback using WAV audio files to confirm button-control selections.
This feature was added as an exercise in WAV audio file recording and playback. The main idea behind the function is to speak the function that was chosen via the control buttons. If the user clicks the Play button, the application says "Play" and begins to play the CD.
The wave audio prompts were created by using the Sound Recorder application found in the accessories section of Windows. After the individual files were created, the sounds were merged back into one large WAV file which contains all of the audio prompts. You may be asking yourself, "Why do such a goofy thing?" In general, it is much easier to open up the WAV audio device with one file, play that file, and close the device. But this is an expert solutions book and the techniques presented here solve a problem you could run into in the future.
The basic idea behind this theory is that it is better to send one large file rather than many smaller files that take up the same amount of space. If one file can contain all of the prompts that are necessary, then installation becomes easier to manage and troubleshooting becomes easier.
The additional bonus of concatenating the WAV files is the ability to safeguard your application from tampering. For example, you may have intended your application to be distributed with a word from the author. Your friend takes a picture of you that you scan into your machine. You design an "About" form that tells a little about you and your company and has your picture plastered dead center.
Note: As a neat side note, you add to the WAV files that announce other functions in the program by personally describing your pride in the quality of this application. If the WAV files were separate, your speech could easily be replaced by lewd comments from a teen-aged hacker. All of your development efforts were not spent to have your application distributed without your WAV file. To reduce this risk, distributing one WAV file with all of the application's audio prompts and your speech makes tampering more difficult.
The hardest part to the concatenation is figuring out where to begin and end each clip. Using the Sound Recorder application will get you pretty close, and if you have a little "dead-air" or periods of silence on either side of the desired audio clip, the positioning is not as critical. Also, depending on the number of audio clips, the task becomes harder the more clips you add.
If you intend to concatenate any audio clips or need a somewhat higher resolution of time-slicing to determine exactly when a clip begins and ends, it is highly recommended that you purchase an audio file management utility. There are several good shareware utilities, such as CoolWave Editor, that allow you to work with WAV files down to the individual sample. These types of utilities will save you a lot of time and effort if you plan on using this technique.
You understand how WAV files can be strung together to build a single file containing multiple audio clips. You also understand how to index those audio clips. Now you need to know how to play an audio clip from within the concatenated WAV file.
The audio file for the CD Jammer application has nine audio clips built into a single concatenated file. The nine clips are show in Table 15.4.
Table 15.4
Table 15.4 Audio Clips in CD Jammer
Audio Clip | Start Position (Sample Number) | End Position (Sample Number) |
Welcome to CD Jammer | 0 | 16172 |
Goodbye | 18869 | 24467 |
Play | 29030 | 34627 |
Stop | 37946 | 42922 |
Pause | 47277 | 51423 |
Next Track | 56608 | 67805 |
Previous Track | 69464 | 77343 |
Eject | 80869 | 87504 |
Thank You Speech | 89371 | 123999 |
To play the specific clips, the WAV device needs to be opened only once. Then each audio clip can be accessed using the "play" feature bounded by the "from" and "to" fields. Listing 15.6 shows code that accepts the positions as input from the calling function and plays the specified clip. This example shows the Play control calling the audio clip.
Listing 15.6 Audio Clip Playback Example
The rest of the control buttons are activated in the same way by calling the PlayIt function with the correct values indicated in the table. As you can see, it would be fairly straightforward to create a large concatenated file if it were necessary.
Most newer stereo systems have some sort of LED or LCD type of display panel that indicates what station you are listening to, what the volume level is at, and what device you are controlling. Well, the CD Jammer display is taken from the same idea. The panel is made up of several digits that indicate the current track, the total number of tracks, and the playing time of the track and disc. Figure 15.6 shows a close-up view of the LED display.
Fig. 15.6 The LED-style display panel is made up of an array of shapes.
To create the illusion of a LED display panel, a 4 x 6 array of circles was created to form a single digit. The digit was then copied several times to create the remaining digits. Making the digits an array has a couple of advantages. First, copying the digits was far simpler than creating new ones. Second, the array allows the application code to take advantage of the placement when activating the digits.
To further explore this point, see figure 15.7. The two digits in this example are made up of 48 individual circles. The first digit has circles numbered zero through 23 and the second digit has circles numbered 24 through 47. These circles, when colored in a specific pattern, will display numbers.
Fig. 15.7 A digit array shows how the shapes are arranged.
By exploiting the arrangement of the array of circles, the same code can be made to activate any one digit with a particular value. For example, if we take a very simple example of the number 1 and chart its pattern according to the array, the binary representation can be gathered (see fig. 15.8).
Fig. 15.8 Charting a digit within the shape array will help develop the code to display the number.
After the binary "on's" and "off's" are charted, the code to create the visual representation can be implemented. Listing 15.7 shows how the individual circles are colored appropriately for the number 1. Figure 15.9 shows how the code looks when the program is run.
Listing 15.7 Creating the Number One on the Digit Array
Fig. 15.9 The number 1 created by the sample code is shown displayed in the shape array.
The sample function shown in Listing 15.7 is not very practical if you have more than one digit. Since CD Jammer has six digits, much of the code would be duplicated if a separate function was produced for each number that each digit would display.
To alleviate the repetitive and unnecessary coding, it is useful to create a digit function where your application can pass the digit position and the number that the digit should display. That way, the code for each of the digits would be the same code with different parameters. For a complete listing that shows how the digits function performs this operation see the CDJAMMER.FRM module in the CD Jammer sample on the CD.
The digits function can now be called to display a number by any function. This function could be extended to include the alphabet or any other special characters. Listing 15.8 show how the tracks, minutes, and seconds are updated and shown in CD Jammer's main form.
Listing 15.8 CDJAMMER.FRM—The LEDUpdate() Function Calls the Digits Function
This chapter has shown you how to apply multimedia technology to your applications. We've discussed and presented examples using the Multimedia MCI control and the MCI APIs. This chapter presented various ways in which to entertain your users, store and retrieve data, give yourself deserving recognition, and provide familiar visual user feedback.
Multimedia continues to be a very hot buzzword in both the computer trade journals and the popular press. Building with these tools will become more prevalent as interfaces to non-computer peripherals such as toasters and microwaves becomes possible. Just remember, it takes a lot of time to perfect your multimedia skills.
For additional topics and some other advanced topics to enhance your multimedia applications check out these chapters as good starting places to investigate and learn more:
| Previous Chapter | Next Chapter | Search | Table of Contents | Book Home Page |
| Buy This Book | Que Home Page | Digital Bookshelf | Disclaimer |
To order books from QUE, call us at 800-716-0044 or 317-361-5400.
For comments or technical support for our books and software, select Talk to Us.
© 1996, QUE Corporation, an imprint of Macmillan Publishing USA, a Simon and Schuster Company.