home *** CD-ROM | disk | FTP | other *** search
/ NEXT Generation 27 / NEXT27.iso / pc / demos / emperor / dx3.exe / SDK / SAMPLES / DSSHOW3D / FILEINFO.CPP < prev    next >
C/C++ Source or Header  |  1996-08-28  |  42KB  |  1,471 lines

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // FileInfo.cpp
  4. //
  5. //   Implementation of the FileInfo class, which is the main class used to
  6. // data and user interface elements associated with a sound buffer in DSShow3D.
  7. //
  8. //
  9.  
  10.  
  11. #include <windows.h>
  12. #include <windowsx.h>
  13. #include <mmsystem.h>
  14. #include <dsound.h>
  15. #include <commctrl.h>
  16.  
  17. #include "DSShow3D.h"
  18. #include "GVars.h"
  19. #include "FileInfo.h"
  20. #include "wave.h"
  21. #include "debug.h"
  22.  
  23.  
  24. int FileInfo::m_xNextPos = 0;
  25. int FileInfo::m_yNextPos = 0;
  26.  
  27. ///////////////////////////////////////////////////////////////////////////////
  28. // FileInfo()
  29. //
  30. //    Class constructor -- the pmw parameter defaults to NULL, but it should be
  31. // something useful before the class is really used.
  32. //
  33. FileInfo::FileInfo( MainWnd *pmw )
  34. {
  35.     m_pmwOwner = pmw;
  36.     m_pbData = NULL;
  37.     m_pwfx = NULL;
  38.     ZeroMemory( m_szFileName, sizeof(m_szFileName));
  39.     m_nFileIndex = 0;
  40.     m_hwndInterface = NULL;
  41.     ZeroMemory( &m_ht, sizeof(HWNDTABLE));
  42.     m_dwInternalFlags = 0;
  43.     m_fPlayButtonSaysPlay = TRUE;
  44.  
  45.     ZeroMemory( &m_dsbd, sizeof(DSBUFFERDESC));
  46.     m_pDSB = NULL;
  47. }
  48.  
  49.  
  50. ///////////////////////////////////////////////////////////////////////////////
  51. // ~FileInfo()
  52. //
  53. //    Class destructor.
  54. //
  55. FileInfo::~FileInfo()
  56. {
  57.     m_pmwOwner = NULL;
  58.  
  59.     if( m_pDSB != NULL )
  60.     {
  61.     m_pDSB->Release();
  62.     m_pDSB = NULL;
  63.     }
  64.     if( m_pwfx )
  65.     {
  66.     GlobalFree( m_pwfx );
  67.     m_pwfx = NULL;
  68.     }
  69.     if( m_pbData )
  70.     {
  71.     GlobalFree( m_pbData );
  72.     m_pbData = NULL;
  73.     }
  74. }
  75.  
  76.  
  77. ///////////////////////////////////////////////////////////////////////////////
  78. // SetFileName()
  79. //
  80. //    Set the internal filename data variable and implicitly update the caption   
  81. // to reflect the change.
  82. //
  83. void FileInfo::SetFileName( LPSTR lpsz, int nIndx )
  84. {
  85.     lstrcpy( m_szFileName, lpsz );
  86.     m_nFileIndex = nIndx;
  87.  
  88.     // If this Assert fails, then we were handed a bad index value
  89.     ASSERT( m_nFileIndex < lstrlen( m_szFileName ));
  90.  
  91.     UpdateFileName();
  92. }
  93.  
  94.  
  95. ///////////////////////////////////////////////////////////////////////////////
  96. // LoadWave()
  97. //
  98. //    Given a filename and an index to the partial filename (i.e. an index into
  99. // the possibly full pathname where the actual filename begins), this function
  100. // will do everything needed to load a file into the FileInfo structure.
  101. //
  102. // Returns 0 on success, non-zero on failure.
  103. //
  104. int FileInfo::LoadWave( LPSTR lpszFile, int nIndx )
  105. {
  106.     SetFileName( lpszFile, nIndx );
  107.  
  108.     // TODO: Need to add in support for ACM filters here
  109.  
  110.     // TODO: Need to determine what's "too big" to load static and then
  111.     //       setup something for streaming the buffer instead.
  112.     if( WaveLoadFile( m_szFileName, &m_cbDataSize, &m_pwfx, &m_pbData ) != 0 )
  113.     {
  114.     // There had better be a MainWnd object, or something is really messed
  115.     ASSERT( m_pmwOwner );
  116.     m_pmwOwner->MessageBox( "Bad wave file or file too big to fit in memory",
  117.                             MB_OK|MB_ICONSTOP );
  118.     goto LW_Error;
  119.     }
  120.  
  121.     if( NewDirectSoundBuffer() != 0 )
  122.     {
  123.     // There had better be a MainWnd object, or something is really messed
  124.     ASSERT( m_pmwOwner );
  125.     m_pmwOwner->MessageBox( "Cannot create new DirectSoundBuffer object",
  126.                             MB_OK|MB_ICONSTOP );
  127.     goto LW_Error;
  128.     }
  129.  
  130.     m_dwInternalFlags |= FI_INTERNALF_LOADED;
  131.  
  132.     // If we haven't failed in loading so far, this point will be a valid
  133.     // pointer to the wave's data.
  134.     ASSERT( NULL != m_pbData );
  135.  
  136.     // Create the ControlPod interface object
  137.     CreateInterface( m_pmwOwner->GetHwnd());
  138.  
  139.     return 0;
  140.  
  141. LW_Error:
  142.     return -1;
  143. }
  144.  
  145.  
  146. ///////////////////////////////////////////////////////////////////////////////
  147. // NewDirectSoundBuffer()
  148. //
  149. //    This function does all the work to create a new DirectSound buffer, and
  150. // gets the interface pointers for both 2D and 3D (if the buffer is 3D).
  151. //
  152. int FileInfo::NewDirectSoundBuffer()
  153.     {
  154.     DSBCAPS         dsbc;
  155.     HRESULT         hr;
  156.     BYTE            *pbWrite1   = NULL;
  157.     BYTE            *pbWrite2    = NULL;
  158.     DWORD           cbLen1;
  159.     DWORD           cbLen2;
  160.  
  161.     /* Set up the direct sound buffer. */
  162.     m_dsbd.dwSize       = sizeof(DSBUFFERDESC);
  163.  
  164.     // We already set the flags to zero in the constructor.  Don't do it again
  165.     // or we might wipe out anything a derived class has setup.
  166.     m_dsbd.dwFlags    |= DSBCAPS_STATIC;
  167.     m_dsbd.dwFlags    |= DSBCAPS_CTRLDEFAULT;   // !!! default
  168.     // The derived class will pick its 3D flags
  169.     if( m_dwInternalFlags & IsSticky())
  170.         {
  171.     ASSERT( !IsGlobal());
  172.     m_dsbd.dwFlags |= DSBCAPS_STICKYFOCUS;
  173.     }
  174.     if( m_dwInternalFlags & IsGlobal())
  175.     {
  176.     ASSERT( !IsSticky());
  177.         m_dsbd.dwFlags |= DSBCAPS_GLOBALFOCUS;
  178.     }
  179.  
  180.     // This flag can only be set if the open dialog detected emulation and
  181.     // allowed the proper radio buttons to be enabled
  182.     if( m_dwInternalFlags & IsUsingGetPos2())
  183.     m_dsbd.dwFlags |= DSBCAPS_GETCURRENTPOSITION2;
  184.  
  185.     m_dsbd.dwBufferBytes    = m_cbDataSize;
  186.     m_dsbd.lpwfxFormat      = m_pwfx;
  187.  
  188.     /* Make sure these are NULL before we start */    
  189.     m_pDSB = NULL;
  190.  
  191.     if( FAILED( hr = gpds->CreateSoundBuffer( &m_dsbd, &m_pDSB, NULL )))
  192.     {
  193.     goto ERROR_IN_ROUTINE;
  194.     }
  195.  
  196.     /* Ok, lock the sucker down, and copy the memory to it. */
  197.     if( FAILED( hr = m_pDSB->Lock( 0, m_cbDataSize, &pbWrite1, &cbLen1,
  198.                         &pbWrite2, &cbLen2, 0L )))
  199.     {
  200.     goto ERROR_IN_ROUTINE;
  201.     }
  202.  
  203.     ASSERT( pbWrite1 != NULL );
  204.     ASSERT( cbLen1 == m_cbDataSize );
  205.  
  206.     CopyMemory( pbWrite1, m_pbData, m_cbDataSize );
  207.  
  208.     ASSERT( 0 == cbLen2 );
  209.     ASSERT( NULL == pbWrite2 );
  210.  
  211.     /* Ok, now unlock the buffer, we don't need it anymore. */
  212.     if( FAILED( hr = m_pDSB->Unlock( pbWrite1, m_cbDataSize, pbWrite2, 0 )))
  213.     {
  214.     goto ERROR_IN_ROUTINE;
  215.     }
  216.  
  217.     pbWrite1 = NULL;
  218.  
  219.     if (FAILED(hr = m_pDSB->SetVolume( MAXVOL_VAL )))
  220.     {
  221.     goto ERROR_IN_ROUTINE;
  222.     }
  223.  
  224.     if (!Is3D()) {
  225.         if( FAILED( hr = m_pDSB->SetPan( MIDPAN_VAL )))
  226.         {
  227.         goto ERROR_IN_ROUTINE;
  228.         }
  229.     }
  230.  
  231.     dsbc.dwSize = sizeof(dsbc);
  232.     if( hr = m_pDSB->GetCaps( &dsbc ))
  233.     {
  234.     goto ERROR_IN_ROUTINE;
  235.     }
  236.  
  237.     if( dsbc.dwFlags & DSBCAPS_LOCHARDWARE )
  238.     {
  239.     m_dwInternalFlags |= FI_INTERNALF_HARDWARE;
  240.     }
  241.     else
  242.     {
  243.     m_dwInternalFlags &= ~FI_INTERNALF_HARDWARE;
  244.     }
  245.  
  246.     goto DONE_ROUTINE;
  247.  
  248. ERROR_IN_ROUTINE:
  249.     if( pbWrite1 != NULL )
  250.     {
  251.     hr = m_pDSB->Unlock( pbWrite1, m_cbDataSize, pbWrite2, 0 );
  252.     pbWrite1 = NULL;
  253.     }
  254.  
  255.     if( NULL != m_pDSB )
  256.     {
  257.     m_pDSB->Release();
  258.     m_pDSB = NULL;
  259.     }
  260.  
  261. DONE_ROUTINE:
  262.     return hr;
  263.     }
  264.  
  265.  
  266. ///////////////////////////////////////////////////////////////////////////////
  267. // SendDestroyRequest()
  268. //
  269. //    Ask the owning window object to destroy us and remove any information
  270. // it may be keeping about our existence.
  271. //
  272. void FileInfo::SendDestroyRequest()
  273.     {
  274.     // We must have an owner to send the request to.  We should never
  275.     // have gotten any further than the CreateInterface() without one.
  276.     ASSERT( NULL != m_pmwOwner );
  277.  
  278.     m_pmwOwner->DestroyFileInfo( this );
  279.     }
  280.  
  281.  
  282. ///////////////////////////////////////////////////////////////////////////////
  283. // SendDestroyRequest()
  284. //
  285. //    Plays a buffer or updates playback flags according to some class state
  286. // variables like our looping flag.
  287. //
  288. void FileInfo::PlayBuffer( void )
  289. {
  290.     if( m_pDSB )
  291.     {
  292.     if( IsLooped())
  293.         m_pDSB->Play( 0, 0, DSBPLAY_LOOPING );
  294.     else
  295.         m_pDSB->Play( 0, 0, 0 );
  296.  
  297.     m_dwInternalFlags |= FI_INTERNALF_PLAYING;
  298.     }
  299. }
  300.  
  301.  
  302. ///////////////////////////////////////////////////////////////////////////////
  303. // StopBuffer()
  304. //
  305. //    Stop the buffer and reset it's position to the start.
  306. //
  307. void FileInfo::StopBuffer( void )
  308. {
  309.     if( m_pDSB )
  310.     {
  311.     m_pDSB->Stop();
  312.     m_pDSB->SetCurrentPosition( 0 );
  313.  
  314.     // Clear our internal state bit
  315.     m_dwInternalFlags &= ~FI_INTERNALF_PLAYING;
  316.     }
  317. }
  318.  
  319.  
  320. void FileInfo::Close( void )
  321.     {
  322.     SendMessage( m_hwndInterface, WM_COMMAND, MAKELONG(IDCANCEL, 0), 0L );
  323.     }
  324.  
  325.  
  326. ///////////////////////////////////////////////////////////////////////////////
  327. // DuplicateBuffer()
  328. //
  329. //    Initializes this FileInfo object by duplicating the given one.
  330. //
  331. void FileInfo::Duplicate( FileInfo *pfiSource )
  332.     {
  333.     if( NULL == pfiSource || NULL == pfiSource->m_pDSB ||
  334.     !(pfiSource->m_dwInternalFlags & FI_INTERNALF_LOADED))
  335.     return;
  336.  
  337.     m_cbDataSize = pfiSource->m_cbDataSize;
  338.     m_nFileIndex = pfiSource->m_nFileIndex;
  339.     m_dwInternalFlags = pfiSource->m_dwInternalFlags;
  340.     m_pmwOwner = pfiSource->m_pmwOwner;
  341.  
  342.     m_pwfx = (PWAVEFORMATEX)new BYTE[sizeof(WAVEFORMATEX)
  343.                     + pfiSource->m_pwfx->cbSize];
  344.     m_pbData = new BYTE[pfiSource->m_cbDataSize];
  345.  
  346.     CopyMemory( m_pbData, pfiSource->m_pbData, pfiSource->m_cbDataSize );
  347.     CopyMemory( m_pwfx, pfiSource->m_pwfx,
  348.         sizeof(WAVEFORMATEX) + pfiSource->m_pwfx->cbSize);
  349.     CopyMemory( &m_dsbd, &pfiSource->m_dsbd, sizeof(m_dsbd));
  350.     CopyMemory( &m_szFileName, pfiSource->m_szFileName, sizeof(m_szFileName));
  351.  
  352.     ASSERT( NULL != pfiSource->m_pDSB );
  353.     ASSERT( NULL != gpds );
  354.  
  355.     HRESULT hr;
  356.  
  357.     if( FAILED( hr = gpds->DuplicateSoundBuffer(pfiSource->m_pDSB, &m_pDSB)))
  358.     {
  359.     DPF( 0, "Failed to DuplicateSoundBuffer() (%s)", TranslateDSError(hr));
  360.     }
  361.     else
  362.     {
  363.     CreateInterface( m_pmwOwner->GetHwnd());
  364.     }
  365.     }
  366.  
  367.  
  368. ///////////////////////////////////////////////////////////////////////////////
  369. // CreateInterface()
  370. //
  371. //    Creates an interface window. A return of TRUE indicates success.
  372. //
  373. BOOL FileInfo::CreateInterface( HWND hwndOwner )
  374.     {
  375.     m_hwndInterface = CreateDialogParam( ghInst, MAKEINTRESOURCE(IDD_BUFFER),
  376.                    hwndOwner, (DLGPROC)FileInfoDlgProc,
  377.                    (LPARAM)this );
  378.  
  379.     if( NULL == m_hwndInterface )
  380.     goto FICI_Fail;
  381.  
  382.     UpdateFileName();
  383.  
  384.     CascadeWindow();
  385.  
  386.     ShowWindow( m_hwndInterface, SW_SHOW );
  387.  
  388.     // This flag tells us an interface window was successfully created
  389.     m_dwInternalFlags |= FI_INTERNALF_INTERFACE;
  390.     return TRUE;
  391.  
  392.  
  393. FICI_Fail:
  394.     if( m_hwndInterface )
  395.     {
  396.     DestroyWindow( m_hwndInterface );
  397.     m_hwndInterface = NULL;
  398.     }
  399.     // Clear the flag that says we have a good interface window created
  400.     m_dwInternalFlags &= ~FI_INTERNALF_INTERFACE;
  401.     return FALSE;
  402.     }
  403.  
  404.  
  405. ///////////////////////////////////////////////////////////////////////////////
  406. // ResetCascade()
  407. //
  408. //
  409. //
  410. void FileInfo::ResetCascade( void )
  411.     {
  412.     POINT   ptParent;
  413.  
  414.     ptParent.x = ptParent.y = 0;
  415.     ClientToScreen( m_pmwOwner->GetHwnd(), &ptParent );
  416.     m_xNextPos = ptParent.x;
  417.     m_yNextPos = ptParent.y;
  418.     }
  419.  
  420.  
  421. ///////////////////////////////////////////////////////////////////////////////
  422. // MinimizeWindow()
  423. //
  424. //
  425. //
  426. void FileInfo::MinimizeWindow( void )
  427.     {
  428.     ShowWindow( m_hwndInterface, SW_MINIMIZE );
  429.     }
  430.  
  431.  
  432. ///////////////////////////////////////////////////////////////////////////////
  433. // RestoreWindow()
  434. //
  435. //
  436. //
  437. void FileInfo::RestoreWindow( void )
  438.     {
  439.     SendMessage( m_hwndInterface, WM_SYSCOMMAND, SC_RESTORE, 0L );
  440.     }
  441.  
  442.  
  443. ///////////////////////////////////////////////////////////////////////////////
  444. // CascadeWindow()
  445. //
  446. //
  447. //
  448. void FileInfo::CascadeWindow( void )
  449.     {
  450.     RECT    rcWind;
  451.     int     nStep;
  452.  
  453.     // Don't move minimized windows
  454.     if( IsIconic( m_hwndInterface ))
  455.     return;
  456.  
  457.     GetWindowRect( m_hwndInterface, &rcWind );
  458.  
  459.     if( m_xNextPos + (rcWind.right - rcWind.left) > GetSystemMetrics(SM_CXSCREEN))
  460.     ResetCascade();
  461.     else if( m_yNextPos + (rcWind.bottom - rcWind.top) > GetSystemMetrics(SM_CYSCREEN))
  462.     ResetCascade();
  463.  
  464.     SetWindowPos( m_hwndInterface, NULL, m_xNextPos, m_yNextPos,
  465.                     0, 0, SWP_NOSIZE | SWP_NOZORDER );
  466.     // Move diagonally by the height of the title bar
  467.     nStep = GetSystemMetrics(SM_CYCAPTION);
  468.     m_xNextPos += nStep;
  469.     m_yNextPos += nStep;
  470.     }
  471.  
  472.  
  473. ///////////////////////////////////////////////////////////////////////////////
  474. // FileInfoDlgProc()
  475. //
  476. //    Window message callback function for all Interface DLGs'.  Route messages
  477. // to message handler functions
  478. //
  479. BOOL CALLBACK FileInfoDlgProc( HWND hDlg, UINT message,
  480.                         WPARAM wParam, LPARAM lParam )
  481.     {
  482.     FileInfo *pfi;
  483.  
  484.     switch( message )
  485.     {
  486.     // The first step is to stash our class object pointer in the user data
  487.     // and Initialize all our controls and internal data members.
  488.     case WM_INITDIALOG:
  489.         ASSERT( NULL != lParam );
  490.         pfi = (FileInfo *)lParam;
  491.         SetWindowLong( hDlg, DWL_USER, (LONG)pfi );
  492.  
  493.         if( !pfi->OnInitDialog( hDlg, wParam ))
  494.         {
  495.         DestroyWindow( hDlg );
  496.         }
  497.         return TRUE;
  498.  
  499.     // By setting the global variable that tracks the active dialog,
  500.     // we can easily dispatch keyboard messages to the proper dialog
  501.     // through IsDialogMessage() in our main message pump.
  502.     case WM_ACTIVATE:
  503.         if( !wParam )
  504.         ghDlgActive = NULL;
  505.         else
  506.         ghDlgActive = hDlg;
  507.         return TRUE;
  508.  
  509.     case WM_INITMENU:
  510.         pfi = (FileInfo*)GetWindowLong( hDlg, DWL_USER );
  511.         ASSERT( NULL != pfi );
  512.         return pfi->OnInitMenu( wParam, lParam );
  513.  
  514.     case WM_DROPFILES:
  515.         pfi = (FileInfo*)GetWindowLong( hDlg, DWL_USER );
  516.         ASSERT( NULL != pfi );
  517.         return pfi->m_pmwOwner->SendMessage( WM_DROPFILES, wParam, lParam );
  518.  
  519.     case WM_COMMAND:
  520.         pfi = (FileInfo*)GetWindowLong( hDlg, DWL_USER );
  521.         ASSERT( NULL != pfi );
  522.         return pfi->OnCommand( wParam, lParam );
  523.  
  524.     // Handle this to deal with right-clicks on our controls -- we have a
  525.     // bunch of different context menus that we can popup
  526.     case WM_CONTEXTMENU:
  527.         pfi = (FileInfo*)GetWindowLong( hDlg, DWL_USER );
  528.         ASSERT( NULL != pfi );
  529.         return pfi->OnContextMenu( hDlg, LOWORD(lParam), HIWORD(lParam));
  530.  
  531.     // Trackbar slider notifications come through here
  532.     case WM_HSCROLL:
  533.         pfi = (FileInfo*)GetWindowLong( hDlg, DWL_USER );
  534.         ASSERT( NULL != pfi );
  535.         return pfi->OnHScroll( LOWORD(wParam), (LONG)HIWORD(wParam), (HWND)lParam );
  536.  
  537.     case WM_DESTROY:
  538.         pfi = (FileInfo*)GetWindowLong( hDlg, DWL_USER );
  539.         ASSERT( NULL != pfi );
  540.         pfi->OnDestroy();
  541.         return TRUE;
  542.  
  543.     default:
  544.         return FALSE;
  545.     }
  546.  
  547.     ASSERT( FALSE );
  548.     }
  549.  
  550.  
  551. /* OnInitMenu()
  552.  *
  553.  *    Updates the state of items on the menus in response to a WM_INITMENU
  554.  * message, which means the menu is about to be displayed.
  555.  */
  556. BOOL FileInfo::OnInitMenu( WPARAM wParam, LPARAM lParam )
  557.     {
  558.     HMENU   hSys = GetSystemMenu( m_hwndInterface, FALSE );
  559.  
  560.     EnableMenuItem( hSys, SC_MAXIMIZE, MF_BYCOMMAND | MF_GRAYED );
  561.     EnableMenuItem( hSys, SC_SIZE, MF_BYCOMMAND | MF_GRAYED );
  562.     return TRUE;
  563.     }
  564.  
  565.  
  566. /* OnInitDialog()
  567.  *
  568.  *    Handles the initialization of the FilInfo interface window, which is
  569.  * actually a modeless dialog.
  570.  */
  571. BOOL FileInfo::OnInitDialog( HWND hDlg, WPARAM wParam )
  572.     {
  573.     TCHAR   szBuf1[64], tszFmt[64];
  574.  
  575.     // Grab a bunch of handles and store them for easy access later
  576.     m_ht.hPlayButton = GetDlgItem( hDlg, IDC_BUFFERDLG_PLAY_BUTTON );
  577.     m_ht.hLoopedCheck = GetDlgItem( hDlg, IDC_BUFFERDLG_LOOPED_CHECK );
  578.     m_ht.hProgressSlider = GetDlgItem( hDlg, IDC_BUFFERDLG_PROGRESS_SLIDER );
  579.     m_ht.hProgressText = GetDlgItem( hDlg, IDC_BUFFERDLG_PROGRESS_TEXT );
  580.     m_ht.hProgressSpin = GetDlgItem( hDlg, IDC_BUFFERDLG_PROGRESS_SPIN );
  581.     m_ht.hFreqText = GetDlgItem( hDlg, IDC_BUFFERDLG_FREQ_TEXT );
  582.     m_ht.hFreqSlider = GetDlgItem( hDlg, IDC_BUFFERDLG_FREQ_SLIDER );
  583.     m_ht.hVolText = GetDlgItem( hDlg, IDC_BUFFERDLG_VOL_TEXT );
  584.     m_ht.hVolSlider = GetDlgItem( hDlg, IDC_BUFFERDLG_VOL_SLIDER );
  585.     m_ht.hPanText = GetDlgItem( hDlg, IDC_BUFFERDLG_PAN_TEXT );
  586.     m_ht.hPanSlider = GetDlgItem( hDlg, IDC_BUFFERDLG_PAN_SLIDER );
  587.     m_ht.hPlayCursorText = GetDlgItem( hDlg, IDC_BUFFERDLG_PLAYCURSOR_TEXT );
  588.     m_ht.hWriteCursorText = GetDlgItem( hDlg, IDC_BUFFERDLG_WRITECURSOR_TEXT );
  589.     m_ht.hDataFormatText = GetDlgItem( hDlg, IDC_BUFFERDLG_DATAFORMAT_TEXT );
  590.     m_ht.hBufferTypeText = GetDlgItem( hDlg, IDC_BUFFERDLG_BUFFERTYPE_TEXT );
  591.     m_ht.hFocusModeText = GetDlgItem( hDlg, IDC_BUFFERDLG_FOCUS_TEXT );
  592.     m_ht.hGetPosModeText = GetDlgItem( hDlg, IDC_BUFFERDLG_GETPOS_TEXT );
  593.  
  594.     // Load, fill in and set the string describing the format of the sound data
  595.     if( m_pwfx->nChannels == 1 )
  596.     LoadString( ghInst, IDS_DATAFORMAT_MONO, tszFmt, sizeof(tszFmt)-1);
  597.     else
  598.     LoadString( ghInst, IDS_DATAFORMAT_STEREO, tszFmt, sizeof(tszFmt)-1);
  599.     wsprintf( szBuf1, tszFmt, m_pwfx->nSamplesPerSec, m_pwfx->wBitsPerSample );
  600.                         
  601.     Static_SetText( m_ht.hDataFormatText, szBuf1 );
  602.  
  603.     // Set the Buffer Type text to HARDWARE or SOFTWARE
  604.     if( IsHardware())
  605.     LoadString( ghInst, IDS_BUFFERTYPE_HARDWARE, szBuf1, sizeof(szBuf1)-1);
  606.     else
  607.     LoadString( ghInst, IDS_BUFFERTYPE_SOFTWARE, szBuf1, sizeof(szBuf1)-1);
  608.     Static_SetText( m_ht.hBufferTypeText, szBuf1 );
  609.  
  610.     // Set the focus type to LOCAL, STICKY, or GLOBAL
  611.     if( IsSticky())
  612.     LoadString( ghInst, IDS_FOCUSMODE_STICKY, szBuf1, sizeof(szBuf1)-1);
  613.     else if( IsGlobal())
  614.     LoadString( ghInst, IDS_FOCUSMODE_GLOBAL, szBuf1, sizeof(szBuf1)-1);
  615.     else
  616.     LoadString( ghInst, IDS_FOCUSMODE_LOCAL, szBuf1, sizeof(szBuf1)-1);
  617.     Static_SetText( m_ht.hFocusModeText, szBuf1 );
  618.  
  619.     if( Is3D())
  620.     {
  621.     Static_Enable( m_ht.hPanText, FALSE );
  622.     Static_Enable( m_ht.hPanSlider, FALSE );
  623.     }
  624.  
  625.     // Set the range, page size, etc. of our "slider" (trackbar) controls
  626.     SetSliders();
  627.  
  628.     // Update the state of the UI elements that change
  629.     UpdateUI();
  630.     return TRUE;
  631.     }
  632.  
  633.  
  634. ///////////////////////////////////////////////////////////////////////////////
  635. // OnContextMenu()
  636. //
  637. //    Handles a right-click in the client area by popping up a menu if we have
  638. // one we'd like to display, or returning otherwise. TRUE indicates the message
  639. // was "handled" and no further processing is needed.  FALSE means the message
  640. // was not handled.
  641. //
  642. BOOL FileInfo::OnContextMenu( HWND hwnd, int x, int y )
  643.     {
  644.     HMENU   hm, hSub;
  645.     int     nSubMenu = -1, idFrom = 0;
  646.     POINT   pt = { x, y };
  647.     RECT    rectWind1, rectWind2;
  648.  
  649.     // Set the sub-menu to the Frequency context menu if we hit the Freq. Slider
  650.     // or text control
  651.     GetWindowRect( m_ht.hFreqSlider, &rectWind1 );
  652.     GetWindowRect( m_ht.hFreqText, &rectWind2 );
  653.  
  654.     if( PtInRect( &rectWind1, pt ) || PtInRect( &rectWind2, pt ))
  655.     nSubMenu = 0;
  656.  
  657.     // Set the sub-menu to the Volume context menu if we hit the Vol. Slider
  658.     // or text control
  659.     GetWindowRect( m_ht.hVolSlider, &rectWind1 );
  660.     GetWindowRect( m_ht.hVolText, &rectWind2 );
  661.  
  662.     if( PtInRect( &rectWind1, pt ) || PtInRect( &rectWind2, pt ))
  663.     nSubMenu = 1;
  664.  
  665.     // Only have pan on non-3D buffers
  666.     if (!Is3D())
  667.     {
  668.         // Set the sub-menu to the Pan context menu if we hit the Pan Slider
  669.         // or text control
  670.         GetWindowRect( m_ht.hPanSlider, &rectWind1 );
  671.         GetWindowRect( m_ht.hPanText, &rectWind2 );
  672.  
  673.         if( PtInRect( &rectWind1, pt ) || PtInRect( &rectWind2, pt ))
  674.         nSubMenu = 2;
  675.         }
  676.  
  677.     // We didn't detect any "interesting" hotspots, so return as unprocessed.
  678.     if( nSubMenu < 0 )
  679.     return FALSE;
  680.  
  681.     // If we make it here, we're gonna popup a context menu of some sort
  682.  
  683.     // Attempt to load our menu.  If we fail, we still handled the message
  684.     // so return TRUE
  685.     if(( hm = LoadMenu( ghInst, MAKEINTRESOURCE(IDM_POPUPS))) == NULL )
  686.     return TRUE;
  687.  
  688.     hSub = GetSubMenu( hm, nSubMenu );
  689.     TrackPopupMenu( hSub, TPM_LEFTALIGN | TPM_RIGHTBUTTON,
  690.             pt.x, pt.y, 0, m_hwndInterface, NULL );
  691.     
  692.     DestroyMenu( hm );
  693.  
  694.     return TRUE;
  695.     }
  696.  
  697.  
  698. ///////////////////////////////////////////////////////////////////////////////
  699. // SetSliders()
  700. //
  701. //    Sets the range, page size, tic frequency, and other parameters of all the
  702. // trackbar controls we use in the interface.
  703. //
  704. void FileInfo::SetSliders( void )
  705.     {
  706.     DWORD   dSampleRateRange = FREQ_SLIDER_MAX - FREQ_SLIDER_MIN;
  707.     UDACCEL udAccel;
  708.  
  709.     // Scale the sample rate range into an acceptable span and keep
  710.     // track of the multiplying constant we'll have to use later when
  711.     // we want to set positions based on real values
  712.     m_dwFreqSliderFactor = 1;
  713.     while( dSampleRateRange > 10000 )
  714.     {
  715.     dSampleRateRange /= 10;
  716.     m_dwFreqSliderFactor *= 10;
  717.     }
  718.  
  719.     SendMessage( m_ht.hFreqSlider, TBM_SETRANGEMIN,
  720.             FALSE, (LPARAM)FREQ_SLIDER_MIN / m_dwFreqSliderFactor );
  721.     SendMessage( m_ht.hFreqSlider, TBM_SETRANGEMAX,
  722.             FALSE, (LPARAM)FREQ_SLIDER_MAX / m_dwFreqSliderFactor );
  723.     SendMessage( m_ht.hFreqSlider, TBM_SETPAGESIZE, 0,
  724.                 FREQ_SLIDER_PAGESIZE_HZ / m_dwFreqSliderFactor );
  725.  
  726.     SendMessage( m_ht.hProgressSpin, UDM_SETBUDDY, (WPARAM)m_ht.hProgressSlider, 0 );
  727.     SendMessage( m_ht.hProgressSpin, UDM_SETRANGE, 0, MAKELONG(PROGRESS_MAX, PROGRESS_MIN));
  728.     SendMessage( m_ht.hProgressSpin, UDM_SETPOS, 0, MAKELONG(0,0));
  729.     udAccel.nSec = 0;
  730.     udAccel.nInc = PROGRESS_MAX / 20;
  731.     SendMessage( m_ht.hProgressSpin, UDM_SETACCEL, 1, (LPARAM)&udAccel );
  732.  
  733.     SendMessage( m_ht.hProgressSlider, TBM_SETRANGEMIN, FALSE, (LPARAM)PROGRESS_MIN );
  734.     SendMessage( m_ht.hProgressSlider, TBM_SETRANGEMAX, FALSE, (LPARAM)PROGRESS_MAX );
  735.     SendMessage( m_ht.hProgressSlider, TBM_SETPAGESIZE, FALSE, (LPARAM)PROGRESS_MAX / 20 );
  736.     SendMessage( m_ht.hProgressSlider, TBM_SETTICFREQ, (WPARAM)PROGRESS_TIC, 0 );
  737.  
  738.     // Intentionally set the range backwards because a large number means
  739.     // a smaller value
  740.     SendMessage( m_ht.hVolSlider, TBM_SETRANGEMIN, FALSE,
  741.         (LPARAM)(VOL_MIN + VOL_SLIDER_SHIFT) / VOL_SLIDER_FACTOR );
  742.     SendMessage( m_ht.hVolSlider, TBM_SETRANGEMAX, FALSE,
  743.         (LPARAM)(VOL_MAX + VOL_SLIDER_SHIFT) / VOL_SLIDER_FACTOR );
  744.     SendMessage( m_ht.hVolSlider, TBM_SETPAGESIZE, 0,
  745.         VOL_SLIDER_PAGE / VOL_SLIDER_FACTOR );
  746.     // NOTE: No TICs on the volume slider
  747.  
  748.     SendMessage( m_ht.hPanSlider, TBM_SETRANGEMIN, FALSE,
  749.         (LPARAM)(PAN_MIN + PAN_SLIDER_SHIFT) / PAN_SLIDER_FACTOR );
  750.     SendMessage( m_ht.hPanSlider, TBM_SETRANGEMAX, FALSE,
  751.         (LPARAM)(PAN_MAX + PAN_SLIDER_SHIFT) / PAN_SLIDER_FACTOR );
  752.     SendMessage( m_ht.hPanSlider, TBM_SETPAGESIZE, 0,
  753.         PAN_SLIDER_PAGE / PAN_SLIDER_FACTOR );
  754.     // NOTE: No TICs on the pan slider
  755.  
  756.     // Update the display from the buffer's current settings
  757.     UpdateFreqUI( 0, TRUE );
  758.     UpdateVolUI( 0, TRUE );
  759.     UpdatePanUI( 0, TRUE );
  760.     }
  761.  
  762.  
  763. ///////////////////////////////////////////////////////////////////////////////
  764. // UpdateUI()
  765. //
  766. //    This function is normally called from the MainWnd object's timer handler
  767. // to refresh the UI elements that are time-dependent.  These are things like
  768. // the play and write cursors and the progress.
  769. //
  770. void FileInfo::UpdateUI( void )
  771.     {
  772.     char    szText[8];
  773.     DWORD   dwStatus, dwPlay, dwWrite;
  774.  
  775.     if( NULL == m_pDSB )
  776.     return;
  777.  
  778.     if( FAILED( m_pDSB->GetStatus( &dwStatus )))
  779.     return;
  780.  
  781.     if( dwStatus & DSBSTATUS_BUFFERLOST )
  782.     {
  783.     LPBYTE  pb1, pb2;
  784.     DWORD   cb1, cb2;
  785.  
  786.     if( SUCCEEDED( m_pDSB->Restore()))
  787.         {
  788.         if( SUCCEEDED( m_pDSB->Lock( 0, m_cbDataSize, &pb1, &cb1, &pb2, &cb2, 0 )))
  789.         {
  790.         ASSERT( m_cbDataSize == cb1 );
  791.         if( NULL != m_pbData )
  792.             CopyMemory( pb1, m_pbData, m_cbDataSize );
  793.         m_pDSB->Unlock( pb1, m_cbDataSize, pb2, 0 );
  794.  
  795.         if(IsPlaying())
  796.             PlayBuffer();
  797.         }
  798.         }
  799.     }
  800.     else
  801.     {
  802.     if( dwStatus & DSBSTATUS_PLAYING )
  803.         SetPlaying( TRUE );
  804.     else
  805.         SetPlaying( FALSE );
  806.     }
  807.  
  808.     Button_SetCheck( m_ht.hLoopedCheck, IsLooped());
  809.  
  810.     UpdatePlayButton();
  811.  
  812.     m_pDSB->GetCurrentPosition( &dwPlay, &dwWrite );
  813.     wsprintf( szText, "%u", dwPlay );
  814.     Static_SetText( m_ht.hPlayCursorText, szText );
  815.     wsprintf( szText, "%u", dwWrite );
  816.     Static_SetText( m_ht.hWriteCursorText, szText );
  817.  
  818.     UpdateProgressUI( dwPlay );
  819.  
  820.     return;
  821.     }
  822.  
  823.  
  824. ///////////////////////////////////////////////////////////////////////////////
  825. // UpdateProgressUI()
  826. //
  827. //
  828. //
  829. void FileInfo::UpdateProgressUI( DWORD dwPlayPos )
  830.     {
  831.     char    szText[8];
  832.     FLOAT   fPercentage;
  833.  
  834.     // TODO: Set the progress slider position
  835.     fPercentage = ((FLOAT)dwPlayPos / (FLOAT)(m_cbDataSize-1));
  836.  
  837.     SendMessage( m_ht.hProgressSlider, TBM_SETPOS, TRUE, (LPARAM)(PROGRESS_MAX * fPercentage));
  838.     SendMessage( m_ht.hProgressSpin, UDM_SETPOS, TRUE, MAKELONG((PROGRESS_MAX * fPercentage), 0));
  839.  
  840.     wsprintf( szText, "%i%%", (int)(100 * fPercentage));
  841.     Static_SetText( m_ht.hProgressText, szText );
  842.     }
  843.  
  844. ///////////////////////////////////////////////////////////////////////////////
  845. // UpdateVolUI()
  846. //
  847. //    Updates the position of the volume slider and text. You can specify that
  848. // it get the volume from the buffer by passing TRUE to fFromBuffer, or you can
  849. // specify a volume by putting it in lForceVol and setting fFromBuffer = FALSE.
  850. //
  851. void FileInfo::UpdateVolUI( LONG lForceVol, BOOL fFromBuffer )
  852.     {
  853.     LONG    lVol;
  854.     char    szText[16];
  855.  
  856.     if( fFromBuffer )
  857.         {
  858.     if( NULL != m_pDSB )
  859.         {
  860.         m_pDSB->GetVolume( &lVol );
  861.         }
  862.     else
  863.         lVol = 0;
  864.     }
  865.     else
  866.     lVol = lForceVol;
  867.  
  868.     SendMessage( m_ht.hVolSlider, TBM_SETPOS, (WPARAM)TRUE,
  869.             (LPARAM)(lVol + VOL_SLIDER_SHIFT) / VOL_SLIDER_FACTOR );
  870.  
  871.     // Print volume in decibels
  872.     wsprintf( szText, "%i dB", lVol / 100 );
  873.  
  874.     Static_SetText( m_ht.hVolText, szText );
  875.     }
  876.  
  877.  
  878. ///////////////////////////////////////////////////////////////////////////////
  879. // UpdatePanUI()
  880. //
  881. //    Updates the position of the panning slider and text. You can specify that
  882. // it get the pan from the buffer by passing TRUE to fFromBuffer, or you can
  883. // specify a pan by putting it in lForcePan and setting fFromBuffer = FALSE.
  884. //
  885. void FileInfo::UpdatePanUI( LONG lForcePan, BOOL fFromBuffer )
  886.     {
  887.     LONG    lPan;
  888.     char    szText[16];
  889.  
  890.     if ( Is3D())
  891.     {
  892.     lForcePan = 0;
  893.     fFromBuffer = FALSE;
  894.     }
  895.  
  896.     if( fFromBuffer )
  897.         {
  898.     if( NULL != m_pDSB )
  899.         {
  900.         m_pDSB->GetPan( &lPan );
  901.         }
  902.     else
  903.         lPan = 0;
  904.     }
  905.     else
  906.     lPan = lForcePan;
  907.  
  908.     SendMessage( m_ht.hPanSlider, TBM_SETPOS, (WPARAM)TRUE,
  909.             (LPARAM)(lPan + PAN_SLIDER_SHIFT) / PAN_SLIDER_FACTOR );
  910.  
  911.     // Print pan in decibels
  912.     wsprintf( szText, "%i dB", lPan / 100 );
  913.  
  914.     Static_SetText( m_ht.hPanText, szText );
  915.     }
  916.  
  917.  
  918. ///////////////////////////////////////////////////////////////////////////////
  919. // UpdateFreqUI()
  920. //
  921. //    Updates the position of the freq slider and text. You can specify that
  922. // it get the freq from the buffer by passing TRUE to fFromBuffer, or you can
  923. // specify a freq by putting it in dwForceFreq and setting fFromBuffer = FALSE.
  924. //
  925. void FileInfo::UpdateFreqUI( DWORD dwForceFreq, BOOL fFromBuffer )
  926.     {
  927.     DWORD   dwFreq;
  928.     char    szText[16];
  929.  
  930.     if( fFromBuffer )
  931.         {
  932.     if( NULL != m_pDSB )
  933.         m_pDSB->GetFrequency( &dwFreq );
  934.     else
  935.         dwFreq = 0;
  936.     }
  937.     else
  938.     dwFreq = dwForceFreq;
  939.  
  940.     SendMessage( m_ht.hFreqSlider, TBM_SETPOS,
  941.             (WPARAM)TRUE, (LPARAM)dwFreq / m_dwFreqSliderFactor );
  942.  
  943.     wsprintf( szText, "%u Hz", dwFreq );
  944.  
  945.     Static_SetText( m_ht.hFreqText, szText );
  946.     }
  947.  
  948.  
  949. ///////////////////////////////////////////////////////////////////////////////
  950. // UpdatePlayButton()
  951. //
  952. //    Uses an internal state flag and the "IsPlaying" flag to determine and set
  953. // the proper text (Play/Stop) for the Play button.
  954. //
  955. void FileInfo::UpdatePlayButton( void )
  956.     {
  957.     if( m_fPlayButtonSaysPlay && IsPlaying())
  958.     {
  959.     // Set to "Stop"
  960.     m_fPlayButtonSaysPlay = FALSE;
  961.     Button_SetText( m_ht.hPlayButton, TEXT("Stop"));
  962.     }
  963.     else if( !m_fPlayButtonSaysPlay && !IsPlaying())
  964.     {
  965.     // Set to "Play"
  966.     Button_SetText( m_ht.hPlayButton, TEXT("Play"));
  967.     m_fPlayButtonSaysPlay = TRUE;
  968.     }
  969.     else
  970.     return;
  971.     }
  972.  
  973.  
  974. ///////////////////////////////////////////////////////////////////////////////
  975. // OnHScroll()
  976. //
  977. //    Main message handler for the WM_HSCROLL message.  this function basically
  978. // figures out which horizontal scrolling control is responsible for sending
  979. // the message and passes on handling to an appropriate function for handling.
  980. //
  981. BOOL FileInfo::OnHScroll( WORD wNotification, LONG lPos, HWND hControl )
  982.     {
  983.     if( !hControl )
  984.     return FALSE;
  985.     
  986.     if( hControl == m_ht.hProgressSpin )
  987.     {
  988.     HandleProgressSpinScroll( wNotification, lPos );
  989.     return TRUE;
  990.     }
  991.     else if( hControl == m_ht.hProgressSlider )
  992.     {
  993.     HandleProgressSliderScroll( wNotification, lPos );
  994.     return TRUE;
  995.     }
  996.     else if( hControl == m_ht.hFreqSlider )
  997.     {
  998.     HandleFreqSliderScroll( wNotification, lPos );
  999.     return TRUE;
  1000.     }
  1001.     else if( hControl == m_ht.hVolSlider )
  1002.     {
  1003.     HandleVolSliderScroll( wNotification, lPos );
  1004.     return TRUE;
  1005.     }
  1006.     else if( hControl == m_ht.hPanSlider )
  1007.     {
  1008.     HandlePanSliderScroll( wNotification, lPos );
  1009.     return TRUE;
  1010.     }
  1011.     else
  1012.     return FALSE;
  1013.     }
  1014.  
  1015.  
  1016. ///////////////////////////////////////////////////////////////////////////////
  1017. // HandleFreqSliderScroll()
  1018. //
  1019. //    Helper function for OnHScroll() which handles the WM_HSCROLL message for
  1020. // the Frequency slider.  Figures out the next position, sets it, and updates
  1021. // the UI elements that are affected (text).
  1022. //
  1023. void FileInfo::HandleFreqSliderScroll( WORD wNot, LONG lPos )
  1024.     {
  1025.     DWORD dwFreq;
  1026.  
  1027.     switch( wNot )
  1028.     {
  1029.     case TB_THUMBTRACK:
  1030.         if( NULL != m_pDSB )
  1031.         {
  1032.         if( SUCCEEDED( m_pDSB->SetFrequency( lPos * m_dwFreqSliderFactor )))
  1033.             {
  1034.             UpdateFreqUI( lPos * m_dwFreqSliderFactor, FALSE );
  1035.             }
  1036.         }
  1037.         break;
  1038.  
  1039.     case TB_ENDTRACK:
  1040.     case TB_LINEDOWN:
  1041.     case TB_LINEUP:
  1042.     case TB_PAGEDOWN:
  1043.     case TB_PAGEUP:
  1044.         lPos = SendMessage( m_ht.hFreqSlider, TBM_GETPOS, 0, 0 );
  1045.         if( NULL != m_pDSB )
  1046.         {
  1047.         if( SUCCEEDED( m_pDSB->SetFrequency( lPos * m_dwFreqSliderFactor )))
  1048.             {
  1049.             UpdateFreqUI( lPos * m_dwFreqSliderFactor, FALSE );
  1050.             }
  1051.         else
  1052.             {
  1053.             if( SUCCEEDED( m_pDSB->GetFrequency( &dwFreq )))
  1054.             {
  1055.             SendMessage( m_ht.hFreqSlider, TBM_SETPOS,
  1056.                     TRUE, dwFreq / m_dwFreqSliderFactor );
  1057.             }
  1058.             }
  1059.         }
  1060.         break;
  1061.     }
  1062.     
  1063.     }
  1064.  
  1065.  
  1066. ///////////////////////////////////////////////////////////////////////////////
  1067. // HandleProgressSliderScroll()
  1068. //
  1069. //
  1070. //
  1071. void FileInfo::HandleProgressSliderScroll( WORD wNot, LONG lPos )
  1072.     {
  1073.     BOOL fUpdate = TRUE;
  1074.  
  1075.     switch( wNot )
  1076.     {
  1077.     case TB_THUMBTRACK:
  1078.         if( IsPlaying())
  1079.         fUpdate = FALSE;
  1080.         break;
  1081.  
  1082.     case TB_ENDTRACK:
  1083.         fUpdate = FALSE;
  1084.         break;
  1085.     case TB_LINEDOWN:
  1086.     case TB_LINEUP:
  1087.     case TB_PAGEDOWN:
  1088.     case TB_PAGEUP:
  1089.         lPos = SendMessage( m_ht.hProgressSlider, TBM_GETPOS, 0, 0 );
  1090.         break;
  1091.  
  1092.     default:
  1093.         fUpdate = FALSE;
  1094.     }
  1095.     
  1096.     if( fUpdate && NULL != m_pDSB )
  1097.     {
  1098.     FLOAT   fPercentage = ((FLOAT)lPos / 10000);
  1099.  
  1100.     m_pDSB->SetCurrentPosition( (DWORD)(fPercentage * (m_cbDataSize-1)));
  1101.     UpdateUI();
  1102. //  UpdateProgressUI(  (DWORD)(fPercentage * (m_cbDataSize-1)));
  1103.     }
  1104.     }
  1105.  
  1106.  
  1107. ///////////////////////////////////////////////////////////////////////////////
  1108. // HandleProgressSpinScroll()
  1109. //
  1110. //
  1111. //
  1112. void FileInfo::HandleProgressSpinScroll( WORD wNot, LONG lPos )
  1113.     {
  1114.     BOOL fUpdate = TRUE;
  1115.  
  1116.     switch( wNot )
  1117.     {
  1118.     case SB_THUMBPOSITION:
  1119.         lPos = SendMessage( m_ht.hProgressSpin, UDM_GETPOS, 0, 0 );
  1120.         break;
  1121.  
  1122.     default:
  1123.         fUpdate = FALSE;
  1124.     }
  1125.     
  1126.     if( fUpdate && NULL != m_pDSB )
  1127.     {
  1128.     FLOAT   fPercentage = ((FLOAT)lPos / 10000);
  1129.  
  1130.     m_pDSB->SetCurrentPosition( (DWORD)(fPercentage * (m_cbDataSize-1)));
  1131.     UpdateUI();
  1132.     UpdateProgressUI(  (DWORD)(fPercentage * (m_cbDataSize-1)));
  1133.     }
  1134.     }
  1135.  
  1136.  
  1137. ///////////////////////////////////////////////////////////////////////////////
  1138. // HandleVolSliderScroll()
  1139. //
  1140. //    Helper function for OnHScroll() which handles the WM_HSCROLL message for
  1141. // the Volume slider.  Figures out the next position, sets it, and updates
  1142. // the UI elements that are affected (text).
  1143. //
  1144. void FileInfo::HandleVolSliderScroll( WORD wNot, LONG lPos )
  1145.     {
  1146.     BOOL fUpdate = TRUE;
  1147.  
  1148.     switch( wNot )
  1149.     {
  1150.     case TB_THUMBTRACK:
  1151.         break;
  1152.  
  1153.     case TB_ENDTRACK:
  1154.     case TB_LINEDOWN:
  1155.     case TB_LINEUP:
  1156.     case TB_PAGEDOWN:
  1157.     case TB_PAGEUP:
  1158.         lPos = SendMessage( m_ht.hVolSlider, TBM_GETPOS, 0, 0 );
  1159.         break;
  1160.  
  1161.     default:
  1162.         fUpdate = FALSE;
  1163.     }
  1164.     
  1165.     if( fUpdate && NULL != m_pDSB )
  1166.     {
  1167.     m_pDSB->SetVolume( (lPos * VOL_SLIDER_FACTOR) - VOL_SLIDER_SHIFT );
  1168.     DPF( 1, "SetVolume: %i", (lPos * VOL_SLIDER_FACTOR) - VOL_SLIDER_SHIFT );
  1169.     UpdateVolUI( (lPos * VOL_SLIDER_FACTOR) - VOL_SLIDER_SHIFT, FALSE );
  1170.     }
  1171.     }
  1172.  
  1173.  
  1174. ///////////////////////////////////////////////////////////////////////////////
  1175. // HandlePanSliderScroll()
  1176. //
  1177. //    Helper function for OnHScroll() which handles the WM_HSCROLL message for
  1178. // the Pan slider.  Figures out the next position, sets it, and updates the UI
  1179. // elements that are affected (text).
  1180. //
  1181. void FileInfo::HandlePanSliderScroll( WORD wNot, LONG lPos )
  1182.     {
  1183.     BOOL fUpdate = TRUE;
  1184.  
  1185.     switch( wNot )
  1186.     {
  1187.     case TB_THUMBTRACK:
  1188.         break;
  1189.  
  1190.     case TB_ENDTRACK:
  1191.     case TB_LINEDOWN:
  1192.     case TB_LINEUP:
  1193.     case TB_PAGEDOWN:
  1194.     case TB_PAGEUP:
  1195.         lPos = SendMessage( m_ht.hPanSlider, TBM_GETPOS, 0, 0 );
  1196.         break;
  1197.  
  1198.     default:
  1199.         fUpdate = FALSE;
  1200.     }
  1201.     
  1202.     if( fUpdate && NULL != m_pDSB )
  1203.     {
  1204.     m_pDSB->SetPan( (lPos * PAN_SLIDER_FACTOR) - PAN_SLIDER_SHIFT );
  1205.     UpdatePanUI( (lPos * PAN_SLIDER_FACTOR) - PAN_SLIDER_SHIFT, FALSE );
  1206.     }
  1207.     }
  1208.  
  1209.  
  1210. /* OnDestroy()
  1211.  *
  1212.  */
  1213. void FileInfo::OnDestroy()
  1214.     {
  1215.     SendDestroyRequest();
  1216.     return;
  1217.     }
  1218.  
  1219.  
  1220. ///////////////////////////////////////////////////////////////////////////////
  1221. // OnCommand()
  1222. //
  1223. //    Handles WM_COMMAND messages sent to the dialog interface.
  1224. //
  1225. BOOL FileInfo::OnCommand( WPARAM wParam, LPARAM lParam )
  1226.     {
  1227.     ASSERT( NULL != m_hwndInterface );
  1228.  
  1229.     // These three functions break out the handling of the WM_COMMAND messages
  1230.     // that will be sent by various context menus.  There's no real difference
  1231.     // between these and other messages, but keeping them seperate emphasizes
  1232.     // where they come from and keeps our switch a bit shorter.
  1233.     if( HandleFreqContext( wParam ) || HandleVolContext( wParam )
  1234.         || HandlePanContext( wParam ))
  1235.     {
  1236.     return TRUE;
  1237.     }
  1238.  
  1239.     switch( LOWORD( wParam ))
  1240.     {
  1241.     case ID_BUFFERDLG_FILE_OPEN:
  1242.         // For convenience, the File|Open command is on the dialog's menu.
  1243.         // If we see it, we should reflect it to the parent for processing.
  1244.         ASSERT( NULL != m_pmwOwner );
  1245.         SendMessage( m_pmwOwner->GetHwnd(), WM_COMMAND,
  1246.                     MAKEWPARAM( IDC_FILE_OPEN, 0 ), 0L );
  1247.         break;
  1248.  
  1249.     case ID_BUFFERDLG_DUPLICATE:
  1250.         m_pmwOwner->DuplicateBuffer( this );
  1251.         break;
  1252.  
  1253.     case IDCANCEL:
  1254.         // This is what the dialog subsystem will send us when the user
  1255.         // clicks the Close button from the caption bar or the System menu
  1256.         DestroyWindow( m_hwndInterface );
  1257.         break;
  1258.  
  1259.         case IDC_BUFFERDLG_PLAY_BUTTON:
  1260.         // Handle the Play button depending on whether or not the buffer is
  1261.         // playing or stopped.
  1262.         if( IsPlaying())
  1263.         {
  1264.         StopBuffer();
  1265.         }
  1266.         else
  1267.         {
  1268.         PlayBuffer();
  1269.         }
  1270.         UpdatePlayButton();
  1271.         break;
  1272.  
  1273.     case IDC_BUFFERDLG_LOOPED_CHECK:
  1274.         // Toggle the state of the looping flag with an XOR
  1275.         m_dwInternalFlags ^= FI_INTERNALF_LOOPED;
  1276.  
  1277.         // Calling Play will update the looping state in DSound
  1278.         if( IsPlaying())
  1279.         PlayBuffer();
  1280.         break;
  1281.  
  1282.     default:
  1283.         // FALSE means we didn't want to deal with the message
  1284.         return FALSE;
  1285.     }
  1286.  
  1287.     // TRUE means we processed the message
  1288.     return TRUE;
  1289.     }
  1290.  
  1291.  
  1292. ///////////////////////////////////////////////////////////////////////////////
  1293. // UpdateFileName()
  1294. //
  1295. //    Updates the file name which is displayed in the dialog window caption.
  1296. //
  1297. void FileInfo::UpdateFileName( void )
  1298.     {
  1299.     if( NULL != m_hwndInterface )
  1300.     {
  1301.     SendMessage( m_hwndInterface, WM_SETTEXT, 0L,
  1302.                     (LPARAM)&m_szFileName[m_nFileIndex] );
  1303.     }
  1304.     }
  1305.  
  1306.  
  1307. ///////////////////////////////////////////////////////////////////////////////
  1308. // HandlePanContext()
  1309. //
  1310. //    Handle WM_COMMAND messages from the Pan context menu.  Returns TRUE if a
  1311. // message was handled.
  1312. //
  1313. BOOL FileInfo::HandlePanContext( WPARAM wParam )
  1314.     {
  1315.     switch( LOWORD( wParam ))
  1316.     {
  1317.     case ID_PANCONTEXT_CENTER:
  1318.         if( m_pDSB )
  1319.         {
  1320.         m_pDSB->SetPan(0);
  1321.         UpdatePanUI( 0, FALSE );
  1322.         }
  1323.         break;
  1324.     case ID_PANCONTEXT_10DB_LEFT:
  1325.         if( m_pDSB )
  1326.         {
  1327.         m_pDSB->SetPan(-1000);
  1328.         UpdatePanUI( -1000, FALSE );
  1329.         }
  1330.         break;
  1331.     case ID_PANCONTEXT_10DB_RIGHT:
  1332.         if( m_pDSB )
  1333.         {
  1334.         m_pDSB->SetPan(1000);
  1335.         UpdatePanUI( 1000, FALSE );
  1336.         }
  1337.         break;
  1338.     case ID_PANCONTEXT_FULL_LEFT:
  1339.         if( m_pDSB )
  1340.         {
  1341.         m_pDSB->SetPan(-10000);
  1342.         UpdatePanUI( -10000, FALSE );
  1343.         }
  1344.         break;
  1345.     case ID_PANCONTEXT_FULL_RIGHT:
  1346.         if( m_pDSB )
  1347.         {
  1348.         m_pDSB->SetPan(10000);
  1349.         UpdatePanUI( 10000, FALSE );
  1350.         }
  1351.         break;
  1352.  
  1353.     default:
  1354.         return FALSE;
  1355.     }
  1356.  
  1357.     return TRUE;
  1358.     }
  1359.  
  1360.  
  1361. ///////////////////////////////////////////////////////////////////////////////
  1362. // HandleVolContext()
  1363. //
  1364. //    Handle WM_COMMAND messages from the Vol context menu.  Returns TRUE if a
  1365. // message was handled.
  1366. //
  1367. BOOL FileInfo::HandleVolContext( WPARAM wParam )
  1368.     {
  1369.     switch( LOWORD( wParam ))
  1370.     {
  1371.     case ID_VOLCONTEXT_0DB:
  1372.         if( m_pDSB )
  1373.         {
  1374.         m_pDSB->SetVolume(0);
  1375.         UpdateVolUI( 0, FALSE );
  1376.         }
  1377.         break;
  1378.     case ID_VOLCONTEXT_10DB:
  1379.         if( m_pDSB )
  1380.         {
  1381.         m_pDSB->SetVolume(-1000);
  1382.         UpdateVolUI( -1000, FALSE );
  1383.         }
  1384.         break;
  1385.     case ID_VOLCONTEXT_20DB:
  1386.         if( m_pDSB )
  1387.         {
  1388.         m_pDSB->SetVolume(-2000);
  1389.         UpdateVolUI( -2000, FALSE );
  1390.         }
  1391.         break;
  1392.     case ID_VOLCONTEXT_30DB:
  1393.         if( m_pDSB )
  1394.         {
  1395.         m_pDSB->SetVolume(-3000);
  1396.         UpdateVolUI( -3000, FALSE );
  1397.         }
  1398.         break;
  1399.     case ID_VOLCONTEXT_100DB:
  1400.         if( m_pDSB )
  1401.         {
  1402.         m_pDSB->SetVolume(-10000);
  1403.         UpdateVolUI( -10000, FALSE );
  1404.         }
  1405.         break;
  1406.  
  1407.     default:
  1408.         return FALSE;
  1409.     }
  1410.  
  1411.     return TRUE;
  1412.     }
  1413.  
  1414.  
  1415. ///////////////////////////////////////////////////////////////////////////////
  1416. // HandleFreqContext()
  1417. //
  1418. //    Handle WM_COMMAND messages from the Freq context menu.  Returns TRUE if a
  1419. // message was handled.
  1420. //
  1421. BOOL FileInfo::HandleFreqContext( WPARAM wParam )
  1422.     {
  1423.     switch( LOWORD( wParam ))
  1424.     {
  1425.     case ID_FREQCONTEXT_FILEDEFAULT:
  1426.         if( m_pDSB )
  1427.         {
  1428.         if( SUCCEEDED( m_pDSB->SetFrequency(m_pwfx->nSamplesPerSec)))
  1429.             UpdateFreqUI( m_pwfx->nSamplesPerSec, FALSE );
  1430.         }
  1431.         break;
  1432.  
  1433.     case ID_FREQCONTEXT_8000HZ:
  1434.         if( m_pDSB )
  1435.         {
  1436.         if( SUCCEEDED( m_pDSB->SetFrequency(8000)))
  1437.             UpdateFreqUI( 8000, FALSE );
  1438.         }
  1439.         break;
  1440.  
  1441.     case ID_FREQCONTEXT_11025HZ:
  1442.         if( m_pDSB )
  1443.         {
  1444.         if( SUCCEEDED( m_pDSB->SetFrequency(11025)))
  1445.             UpdateFreqUI( 11025, FALSE );
  1446.         }
  1447.         break;
  1448.  
  1449.     case ID_FREQCONTEXT_22050HZ:
  1450.         if( m_pDSB )
  1451.         {
  1452.         if( SUCCEEDED( m_pDSB->SetFrequency(22050)))
  1453.             UpdateFreqUI( 22050, FALSE );
  1454.         }
  1455.         break;
  1456.  
  1457.     case ID_FREQCONTEXT_44100HZ:
  1458.         if( m_pDSB )
  1459.         {
  1460.         if( SUCCEEDED( m_pDSB->SetFrequency(44100)))
  1461.             UpdateFreqUI( 44100, FALSE );
  1462.         }
  1463.         break;
  1464.  
  1465.     default:
  1466.         return FALSE;
  1467.     }
  1468.     return TRUE;
  1469.     }
  1470.  
  1471.