home *** CD-ROM | disk | FTP | other *** search
- //----------------------------------------------------------------------------
- // ObjectWindow
- // Copyright (c) 1995, 1995 by Borland International, All Rights Reserved
- //
- // This example demonstrates the use of MCI APIs in Windows 3.1 in an OWL
- // application:
- //
- // You must have a sound board/Speaker and its device driver installed under
- // Windows 3.1 and be certain that it works -- Use the sound applet in Windows
- // Control Pannel to generate a sound. You may copy one of the .WAV files
- // from the WINDOWS subdirectory in your system to this example's
- // subdirectory.
- //
- // Run the .EXE. Choose File:Open and select a .WAV file. Choose Control:Play
- // to play the waveform. The Control menu lets you stop/play/pause and resume.
- // The scrollbar allows random access through the waveform while it is
- // playing.
- // This example demonstrates the use of the MCI API and a callback via
- // WM_MCINOTIFY.
- //
- //----------------------------------------------------------------------------
- #include <owl/pch.h>
- #include <owl/applicat.h>
- #include <owl/opensave.h>
- #include <owl/framewin.h>
- #include <owl/dc.h>
- #include <owl/menu.h>
- #include <owl/button.h>
- #include <owl/slider.h>
- #include <owl/slider.rh>
- #include <math.h>
- #include <mmsystem.h>
- #include <stdio.h>
- #include "mcisound.h"
-
- #define ID_SCROLL 150 // Scroll bar
- #define TIMER_ID 264 // Unique timer ID.
- #define MCI_PARM2(p) ((long)(void far*)&p)
-
- UINT DeviceId = 0; // The global waveform device opened handle
- BOOL FlushNotify = FALSE;
-
- //----------------------------------------------------------------------------
-
- class TSoundBar : public THSlider {
- public:
- TSoundBar(TWindow* parent, int id, int x, int y, int w, int h,
- TModule* module = 0)
- : THSlider(parent, id, x, y, w, h, IDB_HSLIDERTHUMB, module) {}
-
- void SetInfo(int ratio, long length);
- void SetName(char* name);
-
- //
- // Override TScrollBars virtual functions
- //
- void SBLineUp();
- void SBLineDown();
- void SBPageUp();
- void SBPageDown();
- void SBThumbPosition(int thumbPos);
- void SBTop();
- void SBBottom();
-
- private:
- int WaveRatio;
- long WaveLength;
- char ElementName[255];
-
- void ReposAndPlay(long newPos);
- };
-
-
- void
- TSoundBar::ReposAndPlay(long newPos)
- {
- MCI_PLAY_PARMS MciPlayParm;
- MCI_SEEK_PARMS MciSeekParm;
- MCI_SET_PARMS MciSetParm;
- MCI_OPEN_PARMS MciOpenParm;
- MCI_GENERIC_PARMS MciGenParm;
-
- // Only allow SEEK if playing.
- //
- if (!DeviceId)
- return;
-
- // Close the currently playing wave.
- //
- FlushNotify = TRUE;
- MciGenParm.dwCallback = 0;
- mciSendCommand(DeviceId, MCI_STOP, MCI_WAIT, MCI_PARM2(MciGenParm));
- mciSendCommand(DeviceId, MCI_CLOSE, MCI_WAIT, MCI_PARM2(MciGenParm));
-
- // Open the wave again and seek to new position.
- //
- MciOpenParm.dwCallback = 0;
- MciOpenParm.wDeviceID = DeviceId;
- #if !defined(__WIN32__)
- MciOpenParm.wReserved0 = 0;
- #endif
- MciOpenParm.lpstrDeviceType = 0;
- MciOpenParm.lpstrElementName = ElementName;
- MciOpenParm.lpstrAlias = 0;
-
- if (mciSendCommand(DeviceId, MCI_OPEN, MCI_WAIT| MCI_OPEN_ELEMENT, MCI_PARM2(MciOpenParm))) {
- MessageBox("Open Error", "Sound Play", MB_OK);
- return;
- }
- DeviceId = MciOpenParm.wDeviceID;
-
- // Our time scale is in SAMPLES.
- //
- MciSetParm.dwTimeFormat = MCI_FORMAT_SAMPLES;
- if (mciSendCommand(DeviceId, MCI_SET, MCI_SET_TIME_FORMAT, MCI_PARM2(MciSetParm))) {
- MessageBox("Set Time Error", "Sound Play", MB_OK);
- return;
- }
-
- // Compute new position, remember the scrollbar range has been scaled based
- // on WaveRatio.
- //
- MciSeekParm.dwCallback = 0;
- MciSeekParm.dwTo = (newPos*WaveRatio > WaveLength) ? WaveLength :
- newPos*WaveRatio;
- if (mciSendCommand(DeviceId, MCI_SEEK, MCI_TO, MCI_PARM2(MciSeekParm))) {
- MessageBox("Seek Error", "Sound Play", MB_OK);
- return;
- }
-
- MciPlayParm.dwCallback = (long)HWindow;
- MciPlayParm.dwFrom = 0;
- MciPlayParm.dwTo = 0;
- if (mciSendCommand(DeviceId, MCI_PLAY, MCI_NOTIFY, MCI_PARM2(MciPlayParm))) {
- MessageBox("Play Error", "Sound Play", MB_OK);
- return;
- }
- }
-
- void
- TSoundBar::SetInfo(int ratio, long length)
- {
- WaveRatio = ratio;
- WaveLength = length;
- }
-
- void
- TSoundBar::SetName(char* name)
- {
- strcpy(ElementName, name);
- }
-
- void
- TSoundBar::SBLineUp()
- {
- THSlider::SBLineUp();
- ReposAndPlay(GetPosition());
- }
-
- void
- TSoundBar::SBLineDown()
- {
- THSlider::SBLineDown();
- ReposAndPlay(GetPosition());
- }
-
- void
- TSoundBar::SBPageUp()
- {
- THSlider::SBPageUp();
- ReposAndPlay(GetPosition());
- }
-
- void
- TSoundBar::SBPageDown()
- {
- THSlider::SBPageDown();
- ReposAndPlay(GetPosition());
- }
-
- void
- TSoundBar::SBThumbPosition(int thumbPos)
- {
- THSlider::SBThumbPosition(thumbPos);
- ReposAndPlay(GetPosition());
- }
-
- void
- TSoundBar::SBTop()
- {
- THSlider::SBTop();
- ReposAndPlay(GetPosition());
- }
-
- void
- TSoundBar::SBBottom()
- {
- THSlider::SBBottom();
- ReposAndPlay(GetPosition());
- }
-
-
- //----------------------------------------------------------------------------
-
- class TSoundWindow : public TFrameWindow {
- public:
- TSoundWindow(TWindow* parent, const char far* title);
- ~TSoundWindow();
-
- void SetupWindow();
-
- LRESULT MciNotify(WPARAM, LPARAM);
- void EvPaint();
- void CmFileOpen();
- void CmFileExit();
- void CmPlayWave();
- void CmStopWave();
- void CmHelpAbout();
- void EvTimer(UINT id);
-
- private:
- char ElementName[255];
- int Running;
- int Pause;
- UINT TimeGoing;
- int WaveRatio;
- long WaveLength;
- TSoundBar* SoundBar;
-
- MCI_GENERIC_PARMS MciGenParm;
- MCI_OPEN_PARMS MciOpenParm;
- MCI_PLAY_PARMS MciPlayParm;
- MCI_STATUS_PARMS MciStatusParm;
- MCI_SET_PARMS MciSetParm;
-
- void GetDeviceInfo();
- void StopWave();
- void StopMCI();
-
- DECLARE_RESPONSE_TABLE(TSoundWindow);
- };
-
- DEFINE_RESPONSE_TABLE1(TSoundWindow, TFrameWindow)
- EV_MESSAGE(MM_MCINOTIFY, MciNotify),
- EV_WM_PAINT,
- EV_COMMAND(SM_OPEN, CmFileOpen),
- EV_COMMAND(SM_EXIT, CmFileExit),
- EV_COMMAND(SM_PLAY, CmPlayWave),
- EV_COMMAND(SM_STOP, CmStopWave),
- EV_COMMAND(SM_ABOUT, CmHelpAbout),
- EV_WM_TIMER,
- END_RESPONSE_TABLE;
-
-
- TSoundWindow::TSoundWindow(TWindow* parent, const char far* title)
- : TFrameWindow(parent, title)
- {
- AssignMenu(ID_MENU);
- Attr.AccelTable = IDA_SOUNDPLY;
- Attr.X = 50;
- Attr.Y = 100;
- Attr.W = 400;
- Attr.H = 220;
-
- Running = 0;
- Pause = 0;
- WaveLength = WaveRatio = 0;
- ElementName[0] = 0;
-
- SoundBar = new TSoundBar(this, ID_SCROLL, 50, 67, 300, 40);
-
- new TButton(this, SM_PLAY, "&Play", 50, 120, 50, 20, TRUE);
- new TButton(this, SM_STOP, "&Stop", 120, 120, 50, 20, TRUE);
- }
-
- void
- TSoundWindow::SetupWindow()
- {
- TFrameWindow::SetupWindow();
- SoundBar->SetRange(0, 0);
- SoundBar->SetRuler(0);
- }
-
- TSoundWindow::~TSoundWindow()
- {
- StopMCI();
- }
-
- //
- // EvPaint member function responds to WM_PAINT messages
- //
- void
- TSoundWindow::EvPaint()
- {
- TPaintDC paintDC(HWindow);
-
- // File name.
- //
- if (strlen(ElementName))
- paintDC.TextOut(5, 5, ElementName, strlen(ElementName));
- else
- paintDC.TextOut(5, 5, "<No WAVEFORM file loaded>", 25);
-
- paintDC.TextOut(160, 35, "Samples:", 8);
- paintDC.TextOut(50, 48, "0", 1); // Beginning value.
-
- // Ending number of samples.
- //
- char buffer[10];
- if (WaveLength)
- sprintf(buffer, "%ld", WaveLength);
- else
- strcpy(buffer, "Unknown");
- paintDC.TextOut(315, 48, buffer, strlen(buffer));
- }
-
- void
- TSoundWindow::GetDeviceInfo()
- {
- WAVEOUTCAPS waveOutCaps;
-
- if (!waveOutGetDevCaps(DeviceId, &waveOutCaps, sizeof(waveOutCaps))) {
- MessageBox("GetDevCaps Error", "Sound Play", MB_OK);
- return;
- }
- }
-
- //
- // Play the wave...
- //
- void
- TSoundWindow::CmPlayWave()
- {
- if (!Running) {
- //
- // MCI APIs to open a device and play a .WAV file, using
- // notification to close
- //
- memset(&MciOpenParm, 0, sizeof MciOpenParm);
-
- MciOpenParm.lpstrElementName = ElementName;
-
- if (mciSendCommand(0, MCI_OPEN, MCI_WAIT | MCI_OPEN_ELEMENT,
- MCI_PARM2(MciOpenParm))) {
- MessageBox(
- "Open Error - a waveForm output device is necessary to use this demo.",
- "Sound Play", MB_OK);
- return;
- }
- DeviceId = MciOpenParm.wDeviceID;
-
- // The time format in this demo is in Samples.
- //
- MciSetParm.dwCallback = 0;
- MciSetParm.dwTimeFormat = MCI_FORMAT_SAMPLES;
- if (mciSendCommand(DeviceId, MCI_SET, MCI_SET_TIME_FORMAT, MCI_PARM2(MciSetParm))) {
- MessageBox("SetTime Error", "Sound Play", MB_OK);
- return;
- }
-
- MciPlayParm.dwCallback = (long)HWindow;
- MciPlayParm.dwFrom = 0;
- MciPlayParm.dwTo = 0;
- mciSendCommand(DeviceId, MCI_PLAY, MCI_NOTIFY, MCI_PARM2(MciPlayParm));
-
- // Modify the menu to toggle PLAY to STOP, and enable PAUSE.
- //
- TMenu menu(HWindow);
- menu.ModifyMenu(SM_PLAY, MF_STRING, SM_PLAY, "P&ause\tCtrl+A");
- menu.EnableMenuItem(SM_STOP, MF_ENABLED);
-
- // Make sure the Play/Stop toggle menu knows we're Running.
- //
- Running = TRUE;
-
- // Start a timer to show our progress through the waveform file.
- //
- TimeGoing = SetTimer(TIMER_ID, 200, 0);
-
- // Give enough information to the scrollbar to monitor the
- // progress and issue a re-MCI_OPEN.
- //
- SoundBar->SetName(ElementName);
-
- } else {
- if (!Pause) {
- // Pause the playing.
- //
- MciGenParm.dwCallback = 0;
- mciSendCommand(DeviceId, MCI_PAUSE, MCI_WAIT, MCI_PARM2(MciGenParm));
-
- // Toggle Pause menu to Resume.
- //
- TMenu menu(HWindow);
- menu.ModifyMenu(SM_PLAY, MF_STRING, SM_PLAY, "&Play\tCtrl+P");
- Pause = TRUE;
-
- } else {
- // Resume the playing.
- //
- MciGenParm.dwCallback = 0;
- mciSendCommand(DeviceId, MCI_RESUME, MCI_WAIT, MCI_PARM2(MciGenParm));
-
- // Toggle Resume menu to Pause.
- //
- TMenu menu(HWindow);
- menu.ModifyMenu(SM_PLAY, MF_STRING, SM_PLAY, "P&ause\tCtrl+A");
- Pause = FALSE;
- }
- }
- }
-
- void
- TSoundWindow::CmStopWave()
- {
- StopWave();
- }
-
- void
- TSoundWindow::StopMCI()
- {
- if (TimeGoing) // if Timer is Running, then kill it now.
- TimeGoing = !KillTimer(TIMER_ID);
-
- // Stop playing the waveform file and close the waveform device.
- //
- MciGenParm.dwCallback = 0;
- mciSendCommand(DeviceId, MCI_STOP, MCI_WAIT, MCI_PARM2(MciGenParm));
- mciSendCommand(DeviceId, MCI_CLOSE, MCI_WAIT,MCI_PARM2(MciGenParm));
-
- Running = FALSE;
- DeviceId = 0;
- }
-
- //
- // Reset the menus to Play menu and gray the Pause menu.
- //
- void
- TSoundWindow::StopWave()
- {
- if (DeviceId) {
- StopMCI();
- TMenu menu(HWindow);
- menu.ModifyMenu(SM_PLAY, MF_STRING, SM_PLAY, "&Play\tCtrl+P");
- }
- }
-
- void
- TSoundWindow::CmFileOpen()
- {
- static TOpenSaveDialog::TData data (
- OFN_HIDEREADONLY|OFN_FILEMUSTEXIST,
- "Wave Files (*.WAV)|*.wav|",
- 0,
- 0,
- "WAV"
- );
- if (TFileOpenDialog(this, data).Execute() == IDOK) {
- if (CanClose()) {
- strcpy(ElementName, data.FileName); // Remember the wave file to open.
-
- // Turn the Play menu on.
- TMenu(HWindow).EnableMenuItem(SM_PLAY, MF_ENABLED);
-
- WaveLength = 0;
- WaveRatio = 0;
- SoundBar->SetPosition(0);
- Invalidate();
- }
- }
- }
-
- void
- TSoundWindow::CmFileExit()
- {
- CloseWindow();
- }
-
- //
- // Response function MM_MCINOTIFY message when MCI_PLAY is complete.
- //
- LRESULT
- TSoundWindow::MciNotify(WPARAM, LPARAM)
- {
- if (!FlushNotify) { // Internal STOP/CLOSE, from thumb re-pos?
- StopWave();
-
- // Make sure the thumb is at the end. There could be some WM_TIMER
- // messages on the queue when we kill it, thereby flushing WM_TIMER's
- // from the message queue.
- //
- int loVal, hiVal;
- SoundBar->GetRange(loVal, hiVal);
- SoundBar->SetPosition(hiVal);
-
- } else
- FlushNotify = FALSE; // Yes, so ignore the close.
- return 0;
- }
-
- void
- TSoundWindow::CmHelpAbout()
- {
- MessageBox("SoundPly loads and plays waveform sound "
- "files (*.WAV). The features of this demo are Play/Pause, Stop, "
- "and random seeks through the file via the scollbar (while the sound is "
- "playing). NOTE: SoundPly will only play sounds if the machine contains "
- "a waveForm device, e.g. SoundBlaster, etc.).",
- "About Sound Play", MB_OK);
- }
-
- void
- TSoundWindow::EvTimer(UINT)
- {
- if (!FlushNotify) { // Internal STOP/CLOSE, from thumb re-pos?
- MciStatusParm.dwCallback = 0; // No, normal close.
- MciStatusParm.dwItem = MCI_STATUS_LENGTH;
- mciSendCommand (DeviceId, MCI_STATUS, MCI_STATUS_ITEM, MCI_PARM2(MciStatusParm));
-
- if (WaveLength != MciStatusParm.dwReturn) {
- Invalidate(); // First time it's different update the scrollbar nums
- WaveLength = MciStatusParm.dwReturn;
- }
-
- // Compute the length and ratio and update SoundBar info.
- //
- WaveRatio = int((WaveLength + 32000/2) / 32000);
- if (!WaveRatio)
- WaveRatio = 1;
- SoundBar->SetInfo(WaveRatio, WaveLength);
- SoundBar->SetRange(0, int(WaveLength / WaveRatio));
- SoundBar->SetRuler(int((WaveLength / WaveRatio) / 10));
-
- // Update the current position.
- //
- MciStatusParm.dwCallback = 0;
- MciStatusParm.dwItem = MCI_STATUS_POSITION;
- mciSendCommand(DeviceId, MCI_STATUS, MCI_STATUS_ITEM, MCI_PARM2(MciStatusParm));
-
- SoundBar->SetPosition(int(MciStatusParm.dwReturn / WaveRatio));
- }
-
- FlushNotify = FALSE; // Yes, ignore this close.
- }
-
- //----------------------------------------------------------------------------
-
- class TSoundApp : public TApplication {
- public:
- TSoundApp() : TApplication() {}
- void InitMainWindow() {
- MainWindow = new TSoundWindow(0, "OWL MCI SoundPlay Demo");
- EnableCtl3d();
- }
- };
-
- int
- OwlMain(int /*argc*/, char* /*argv*/ [])
- {
- return TSoundApp().Run();
- }
-