Multimedia Services

   

A growing number of applications today incorporate multimedia elements, such as sound and video, to enrich the experience of the user . Some of the extension libraries Microsoft has provided for Windows include the Multimedia System Library ( mmsystem.dll ), the Microsoft Video for Windows Library ( msvfw32.dll ), and the Microsoft Audio Compression Manager Library ( msacm32.dll ). Originally, multimedia features were not part of the Windows API. However, the Windows operating system has evolved to support and promote multimedia. In fact, the modern Windows platform is, for all practical purposes, a multimedia appliance similar to a TV or stereo. Multimedia devices and data formats, such as MIDI, waveform audio, and video, are supported by Windows. The MMYSTEM.DLL , MSVFW32.DLL , and MSACM32.DLL provide a majority of the basic multimedia capabilities. Microsoft has also introduced a multimedia API known as DirectX to better support games , music, and video. However, this section primarily focuses on the capabilities provided by MMYSTEM.DLL , MSVFW32.DLL , and MSACM32.DLL . The multimedia headers files for these DLLs are DIGITALV.H , MCIAVI.H , MMSYSTEM.H , MSACM.H , VCR.H , and VFW.H .

Table 14.10 describes the various multimedia services provided by these libraries.

Table 14.10. Multimedia Services

Feature

Description

Audio Compression Manager (ACM) Audio Mixers

Provides system-level support for audio compression, decompression , filtering, and conversion (uses MSACM32.DLL ). Provides services to control the routing of audio lines to a destination device for playing or recording. Also provides support for manipulating volume and other effects (uses MMYSTEM.DLL ).

AVICap

Provides video capture capabilities including interface support for acquiring video and waveform-audio hardware and support for controlling streaming video capturing to disk (uses MSVFW32.DLL ).

AVIFile

Provides functions and macros for accessing audio-video inter-leaved (AVI) files (uses MSVFW32.DLL ).

DrawDib

Provide GDI-independent functions used to transfer device-independent bitmaps (DIBs) to video memory (uses MSVFW32.DLL ).

Joysticks

Provides support for managing joysticks and other ancillary input devices that track positions within an absolute coordinate system (touch screen, digitizing tablet, and light pen) (uses MMYSTEM.DLL ).

MCIWnd Window Class

Provides a window class for controlling multimedia devices. Provides support for easily adding multimedia playback or recording capabilities to an application (uses MSVFW32.DLL ).

Media Control Interface (MCI)

Provides device-independent support for playing multimedia devices (waveform audio devices, CD player, MIDI sequencers, and digital-video devices) and recording multimedia resource files (uses MMYSTEM.DLL ).

Multimedia File

Provides buffered and unbuffered file I/O service and support for Resource Interchange File Format (RIFF) files, such as wave files and video files (uses MMYSTEM.DLL ).

Multimedia Timers

Provides support for scheduling periodic, high-resolution timer events (uses MMYSTEM.DLL ).

Music Instrument Digital Interface (MIDI)

Provides the MIDI Mapper to translate and redirect the incoming MIDI messages and other various MIDI services, such as querying for devices and managing, streaming, and recording MIDI message data. (Note: MCI services, which provide a MIDI sequencer, can be used in conjunction with the MIDI services.) (Uses MMYSTEM.DLL .)

Video Compression Manager (VCM)

Provides video data compression and decompression support (uses MSVFW32.DLL ).

Waveform-Audio

Provides utilities for adding (playing and recording) waveform-audio sounds (uses MMYSTEM.DLL ).

Among the three DLLs mentioned in Table 14.10, there are more than 240 functions that support the multimedia services in current versions of Windows. Use Borland's impdef command-line tool or DLL LIB Util , described in the tip earlier, to determine the full list of the available multimedia functions (contained in MMSYSTEM.DLL , MSVFW32.DLL , and MSACM32.DLL ). The import libraries for these DLLs are WINMM.LIB , VFW32.LIB , and MSACM32.LIB , respectively.

Let's now create some simple examples in C++Builder that use several of the Multimedia Services. Later, we'll dive into some deeper, more advanced examples in the Graphics and Multimedia chapter (Chapter 15). Playback of media data and multimedia timers are two useful capabilities that we'll look at now.

Multimedia File Playback

Borland provides a VCL component known as TMediaPlayer that can be used to manipulate and play multimedia clips. TMediaPlayer provides a wrapper to the MCIWnd routines supported by the VFW32.DLL . Although TMediaPlayer is extremely useful, leveraging the MCIWnd routines directly can provide a bit more flexibility and is really not that difficult to use. For example, MCIWndCreate() provides a fairly simple routine that can be used to play CD music, waveform-audio (wave) files, MIDI files, or video clips (see Figure 14.6). The complete source-code example described in this section is provided in the MMedia folder on the CD-ROM that accompanies this book.

Figure 14.6. The multimedia player example using both TMediaPlayer and the Windows MCI.

graphics/14fig06.jpg

The following code snippet shows how the multimedia features provided by the Win32 API can be used to play back a video clip:

 void __fastcall TForm1::SpeedButtonPlayMMFileUsingWin32Click(TObject *Sender)  {    OpenDialog1->DefaultExt = "AVI";    OpenDialog1->FileName = "*.avi";    if (OpenDialog1->Execute())      MCIWndCreate(PanelMCI->Handle,                // window handle to our panel          NULL,                                     // instance handle          WS_VISIBLE  WS_CHILD  MCIWNDF_SHOWALL,  // window styles          OpenDialog1->FileName.c_str());           // filename  } 

In this example, MCIWndCreate() actually creates a VCR-like window (using the MCIWND_WINDOW_CLASS ) containing a play/stop control button, a trackbar, and uses a panel we've placed on the form. If we didn't use the WS_CHILD flag and we identified a NULL window handle, the MCI would have created a brand-new panel for displaying the video if it is a video clip.

Although the MCI can be used to play sound files, a less expensive way to play wave files is to use the PlaySound() function as follows :

 void __fastcall TForm1::SpeedButtonPlayWaveUsingWin32Click(TObject *Sender)  {    OpenDialog1->DefaultExt = "WAV";    OpenDialog1->FileName = "*.wav";    if (OpenDialog1->Execute())      PlaySound(OpenDialog->FileName.c_str(), NULL, SND_ASYNC);  } 

PlaySound() is an extremely useful routine provided by the mmsystem.dll . Often, sound files need to be played in the background of an application, to produce a sound effect, for example. PlaySound does not provide the VCR-like controls or a trackbar as MCIWndCreate() does. Furthermore, sounds are played instantaneously when the PlaySound() function is called.

The DirectSound features supported by DirectX provide additional capabilities for sound manipulation and management enabling multiple sounds to be played simultaneously . Also, DirectShow provides a mechanism to playback compressed sound files such as MP3 and Windows Media Audio (WMA) files, and a wide range of video files including MPEG and Windows Media Video (WMV) files. Discussion of DirectSound and DirectShow, however, are not within the scope of this chapter.

Improved Accuracy with the Multimedia Timer

Borland provides a very simple and easy-to-use VCL timer component known as TTimer . TTimer encapsulates the Win32 API Timer functions. It uses the SetTimer() function to enable timer events, provides an event handler, OnTimer , to respond to WM_TIMER message notifications, and uses the KillTimer() function to disable timer events. When the SetTimer() routine is called, an application requests the Windows System to notify the process (the application) of continual updates until the timer is disabled via the KillTimer() routine. The frequency of these updates is based on the interval provided within the SetTimer() interval timeout parameter (also known as the Interval property value within TTimer ). Although the interval frequency can be identified in milliseconds , timers are not always that accurate. WM_TIMER message notifications might occur more frequently than expected or, if other processes are tying up the system, less frequently than expected. It's never a sure bet. However, there is one way to receive more accurate updates by using the multimedia timers. The multimedia timer is an extension of the original Win32 API and provides better resolution than the standard Windows timer.

Examination of the mmsystem.h file provided by Microsoft and Borland reveals the functions that are available.

 /* timer function prototypes */  WINMMAPI MMRESULT WINAPI timeGetSystemTime(LPMMTIME pmmt, UINT cbmmt);  WINMMAPI DWORD WINAPI timeGetTime(void);  WINMMAPI MMRESULT WINAPI timeSetEvent(UINT uDelay, UINT uResolution,      LPTIMECALLBACK fptc, DWORD dwUser, UINT fuEvent);  WINMMAPI MMRESULT WINAPI timeKillEvent(UINT uTimerID);  WINMMAPI MMRESULT WINAPI timeGetDevCaps(LPTIMECAPS ptc, UINT cbtc);  WINMMAPI MMRESULT WINAPI timeBeginPeriod(UINT uPeriod);  WINMMAPI MMRESULT WINAPI timeEndPeriod(UINT uPeriod); 

In most cases, timeSetEvent() and timeKillEvent() are all that is required to use the multimedia timer. A callback message needs to be defined within your program to handle the multimedia timer event notifications. An example application that compares the standard VCL timer with the multimedia timer is provided both in Listing 14.8 and in the MMTimer folder on the CD-ROM that accompanies this book. Figure 14.7 shows the application running and demonstrates the differences in elapsed time between the two timers.

Figure 14.7. Difference in accuracy between the VCL timer and the multimedia timer.

graphics/14fig07.gif

Listing 14.8 Timer Code
[View full width]
 #include <vcl.h>  #pragma hdrstop  #include "mmtimer.h"  #include <mmsystem.h>  #include <time.h>  //--------------------------------------------------------------------------- #pragma package(smart_init)  #pragma resource "*.dfm"  TFormSystemService *Form1;  //--------------------------------------------------------------------------- __fastcall TForm1::TFormSystemService(TComponent* Owner)          : TForm(Owner)  {          MMTimerID = 0;          MMlasttime = 0;          STANlasttime = 0;  }  //--------------------------------------------------------------------------- void __fastcall TForm1::Timer1Timer(TObject *Sender)  {          unsigned int clocktime = clock();          EditStandardTimer->Text = AnsiString(clocktime - STANlasttime);          STANlasttime = clocktime;  }  //---------------------------------------------------------------------------  void __fastcall TForm1::HandleMMTimerEvent()  {          unsigned int clocktime = clock();          EditMMTimer->Text = AnsiString(clocktime - MMlasttime);          MMlasttime = clocktime;          //Refresh();  }  //--------------------------------------------------------------------------- void CALLBACK TForm1::TimerProc(unsigned int uID, unsigned int uMsg, DWORD dwUser,      DWORD dw1, DWORD dw2)  {          Form1->HandleMMTimerEvent();  }  //--------------------------------------------------------------------------- void __fastcall TForm1::SpeedButtonMMTimerClick(TObject *Sender)  {   if (SpeedButtonMMTimer->Down)   {      int Interval = EditInterval->Text.ToIntDef(0);      int Resolution = EditResolution->Text.ToIntDef(0);  // 0 = greatest possible accuracy      if (Timer1->Interval > 0)      {              MMlasttime = clock();              MMTimerID =  timeSetEvent(Interval, Resolution, TimerProc,NULL, graphics/ccc.gif TIME_PERIODIC);      }   }   else   {      timeKillEvent(MMTimerID);      MMTimerID = 0;   }  }  //--------------------------------------------------------------------------- void __fastcall TForm1::SpeedButtonStandardTimerClick(TObject *Sender)  {     if (SpeedButtonStandardTimer->Down)     {          Timer1->Interval = EditInterval->Text.ToIntDef(0);          STANlasttime = clock();          if (Timer1->Interval > 0)                  Timer1->Enabled = true;     }     else     {          Timer1->Enabled = false;     }  }  //--------------------------------------------------------------------------- void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)  {      if (MMTimerID) timeKillEvent(MMTimerID);  }  

In this example, we kick off each timer with the push of a button; the VCL TTimer and the Win32 API multimedia timer. To get the multimedia timer to work, we provide a user-defined callback called TimerProc() , which is used to handle the timer event as a parameter in the timeSetEvent() API call. Also included with the timeSetEvent() call is the interval and resolution values, both in milliseconds. The resolution is used to indicate the level of accuracy ”the smaller the value, the greater the accuracy. However, a larger value reduces system overhead.

The TimerProc() function behaves just like the Timer1 event handler. The difference is that the multimedia timer will trigger the TimerProc() function closer to the expected mark than the TTimer , expecially under Windows 9X and Windows Me. Finally, when we're done with the timer, a call to timeKillEvent() is made.


   
Top


C++ Builder Developers Guide
C++Builder 5 Developers Guide
ISBN: 0672319721
EAN: 2147483647
Year: 2002
Pages: 253

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net