//----------------------------------------------------------------------------
// File: WinMain.cpp
//
// Desc: Main application file for the PlayStreaming sample. This sample shows 
//       how to load a wave file and play it using a streaming DirectSound 
//       buffer.
//
// Copyright (c) 1999 Microsoft Corp. All rights reserved.
//-----------------------------------------------------------------------------
#define STRICT
#include <windows.h>
#include <commdlg.h>
#include <mmreg.h>
#include <dsound.h>
#include <stdio.h>
#include "resource.h"




//-----------------------------------------------------------------------------
// Function-prototypes
//-----------------------------------------------------------------------------
extern HRESULT  InitDirectSound( HWND hDlg );
extern HRESULT  FreeDirectSound();
extern VOID     LoadWaveFile( HWND hDlg, TCHAR* strFileName );
extern HRESULT  PlayBuffer( BOOL bLooped );
extern HRESULT  StopBuffer();
extern VOID     OnStopSound();
extern BOOL     IsBufferSignaled();
extern HRESULT  HandleNotification( BOOL bLooped );

BOOL CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam );
VOID    OnInitDialog( HWND hDlg );
VOID    OnSliderChanged( HWND hDlg );
VOID    OnOpenSoundFile( HWND hDlg );
HRESULT OnPlaySound( HWND hDlg );
VOID    OnStopSound( HWND hDlg );
VOID    OnEnablePlayUI( HWND hDlg, BOOL bEnable );
VOID    SetFileUI( HWND hDlg, TCHAR* strFileName );




//-----------------------------------------------------------------------------
// Defines, constants, and global variables
//-----------------------------------------------------------------------------
extern HANDLE g_hNotificationEvents[2];




//-----------------------------------------------------------------------------
// Name: WinMain()
// Desc: Entry point for the application.  Since we use a simple dialog for 
//       user interaction we don't need to pump messages.
//-----------------------------------------------------------------------------
INT APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, 
                      INT nCmdShow )
{
    g_hNotificationEvents[0] = CreateEvent( NULL, FALSE, FALSE, NULL );
    g_hNotificationEvents[1] = CreateEvent( NULL, FALSE, FALSE, NULL );

    // Display the main dialog box.
    HWND hDlg = CreateDialog( hInst, MAKEINTRESOURCE(IDD_MAIN), NULL, MainDlgProc );
    ShowWindow( hDlg, SW_NORMAL ); 

    // Init DirectSound
    if( FAILED( InitDirectSound( hDlg ) ) )
    {
        MessageBox( hDlg, "Error initializing DirectSound.  Sample will now exit.", 
                    "DirectSound Sample", MB_OK | MB_ICONERROR );
        EndDialog( hDlg, IDABORT );
        return 1;
    }

    MSG     msg;
    DWORD   dwResult;
    BOOL    bDone = FALSE;
    BOOL    bLooped;
    
    while( !bDone ) 
    { 
        dwResult = MsgWaitForMultipleObjects( 2, g_hNotificationEvents, 
                                              FALSE, INFINITE, QS_ALLEVENTS );
        switch( dwResult )
        {
            case WAIT_OBJECT_0 + 0:
                // g_hNotificationEvents[0] is signaled

                // This means that DirectSound just finished playing 
                // a piece of the buffer, so we need to fill the circular 
                // buffer with new sound from the wav file
                bLooped = ( IsDlgButtonChecked( hDlg, IDC_LOOP_CHECK ) == BST_CHECKED );
                if( FAILED( HandleNotification( bLooped ) ) )
                {
                    MessageBox( hDlg, "Error handling DirectSound notifications."
                               "Sample will now exit.", "DirectSound Sample", 
                               MB_OK | MB_ICONERROR );
                    bDone = TRUE;
                }

                break;

            case WAIT_OBJECT_0 + 1:
                // g_hNotificationEvents[1] is signaled

                // This means that the stop event was signaled, so 
                // update the UI controls to show the sound as stopped
                OnEnablePlayUI( hDlg, TRUE );
                break;

            case WAIT_OBJECT_0 + 2:
                // Messages are available
                while( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) 
                { 
                    if( !IsDialogMessage( hDlg, &msg ) )  
                    {
                        TranslateMessage( &msg ); 
                        DispatchMessage( &msg ); 
                    }

                    if( msg.message == WM_QUIT )
                        bDone = TRUE;
                }
                break;
        }
    }

    // Clean up everything
    FreeDirectSound();

    CloseHandle( g_hNotificationEvents[0] );
    CloseHandle( g_hNotificationEvents[1] );

    return TRUE;
}




//-----------------------------------------------------------------------------
// Name: MainDlgProc()
// Desc: Handles dialog messages
//-----------------------------------------------------------------------------
BOOL CALLBACK MainDlgProc( HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam )
{
    switch (msg) 
    {
    case WM_COMMAND:
        switch ( LOWORD(wParam) )
        {
            case IDC_SOUNDFILE:
                OnOpenSoundFile( hDlg );
                break;

            case IDCANCEL:
                PostQuitMessage( 0 );
                EndDialog( hDlg, IDCANCEL );
                break;

            case IDC_PLAY:
                if( FAILED( OnPlaySound( hDlg ) ) )
                {
                    MessageBox( hDlg, "Error playing DirectSound buffer."
                                "Sample will now exit.", "DirectSound Sample", 
                                MB_OK | MB_ICONERROR );
                    EndDialog( hDlg, IDABORT );
                }
                break;

            case IDC_STOP:
                OnStopSound( hDlg );
                break;

            default:
                return FALSE; // Didn't handle message
        }
        break;

    case WM_INITDIALOG:
        OnInitDialog( hDlg );
        break;

    default:
        return FALSE; // Didn't handle message
    }

    return TRUE; // Handled message
}




//-----------------------------------------------------------------------------
// Name: OnInitDialog()
// Desc: Initializes the dialogs (sets up UI controls, etc.)
//-----------------------------------------------------------------------------
VOID OnInitDialog( HWND hDlg )
{
    // Load the icon
    HINSTANCE hInst = (HINSTANCE) GetWindowLong( hDlg, GWL_HINSTANCE );
    HICON hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDR_MAINFRAME ) );

    // Set the icon for this dialog.
    SendMessage( hDlg, WM_SETICON, ICON_BIG,   (LPARAM) hIcon );  // Set big icon
    SendMessage( hDlg, WM_SETICON, ICON_SMALL, (LPARAM) hIcon );  // Set small icon

    // Set the UI controls
    SetFileUI( hDlg, TEXT("No file loaded.") );
}




//-----------------------------------------------------------------------------
// Name: OnOpenSoundFile()
// Desc: Called when the user requests to open a sound file
//-----------------------------------------------------------------------------
VOID OnOpenSoundFile( HWND hDlg ) 
{
    static TCHAR strFileName[MAX_PATH] = TEXT("");
    static TCHAR strPath[MAX_PATH] = TEXT("");

    // Setup the OPENFILENAME structure
    OPENFILENAME ofn = { sizeof(OPENFILENAME), hDlg, NULL,
                         TEXT("Wave Files\0*.wav\0All Files\0*.*\0\0"), NULL,
                         0, 1, strFileName, MAX_PATH, NULL, 0, strPath,
                         TEXT("Open Sound File"),
                         OFN_FILEMUSTEXIST|OFN_HIDEREADONLY, 0, 0,
                         TEXT(".wav"), 0, NULL, NULL };

    // Get the default media path (something like C:\WINDOWS\MEDIA)
    if( '\0' == strPath[0] )
    {
        GetWindowsDirectory( strPath, MAX_PATH );
        if( strcmp( &strPath[strlen(strPath)], TEXT("\\") ))
            strcat( strPath, TEXT("\\") );
        strcat( strPath, TEXT("MEDIA") );
    }

    OnStopSound( hDlg );

    // Update the UI controls to show the sound as loading a file
    EnableWindow( GetDlgItem( hDlg, IDC_LOOP_CHECK ), FALSE );
    EnableWindow( GetDlgItem( hDlg, IDC_PLAY ),       FALSE );
    EnableWindow( GetDlgItem( hDlg, IDC_STOP ),       FALSE );
    SetFileUI( hDlg, TEXT("Loading file...") );

    // Display the OpenFileName dialog. Then, try to load the specified file
    if( TRUE == GetOpenFileName( &ofn ) )
    {
        SetFileUI( hDlg, TEXT("") );
        LoadWaveFile( hDlg, strFileName );

        // Remember the path for next time
        strcpy( strPath, strFileName );
        char* strLastSlash = strrchr( strPath, '\\' );
        strLastSlash[0] = '\0';
    }
    else
    {
        SetFileUI( hDlg, TEXT("Load aborted.") );
    }
}





//-----------------------------------------------------------------------------
// Name: OnPlaySound()
// Desc: User hit the "Play" button
//-----------------------------------------------------------------------------
HRESULT OnPlaySound( HWND hDlg ) 
{
    HRESULT hr;

    BOOL bLooped = ( IsDlgButtonChecked( hDlg, IDC_LOOP_CHECK ) == BST_CHECKED );
    if( FAILED( hr = PlayBuffer( bLooped ) ) )
        return hr;

    // Update the UI controls to show the sound as playing
    OnEnablePlayUI( hDlg, FALSE );

    return hr;
}




//-----------------------------------------------------------------------------
// Name: OnStopSound()
// Desc: User hit the "stop" button. 
//-----------------------------------------------------------------------------
VOID OnStopSound( HWND hDlg ) 
{
    if( SUCCEEDED( StopBuffer() ) )
    {
        OnEnablePlayUI( hDlg, TRUE );
    }
}




//-----------------------------------------------------------------------------
// Name: OnEnablePlayUI( hDlg,)
// Desc: Enables or disables the Play UI controls 
//-----------------------------------------------------------------------------
VOID OnEnablePlayUI( HWND hDlg, BOOL bEnable )
{
    if( bEnable )
    {
        EnableWindow( GetDlgItem( hDlg, IDC_LOOP_CHECK ), TRUE );
        EnableWindow( GetDlgItem( hDlg, IDC_PLAY ),       TRUE );
        EnableWindow( GetDlgItem( hDlg, IDC_STOP ),       FALSE );
        SetFocus(     GetDlgItem( hDlg, IDC_PLAY ) );
    }
    else
    {
        EnableWindow( GetDlgItem( hDlg, IDC_LOOP_CHECK ), FALSE );
        EnableWindow( GetDlgItem( hDlg, IDC_PLAY ),       FALSE );
        EnableWindow( GetDlgItem( hDlg, IDC_STOP ),       TRUE );
        SetFocus(     GetDlgItem( hDlg, IDC_STOP ) );
    }
}




//-----------------------------------------------------------------------------
// Name: SetStatusUI()
// Desc: Sets the text for the status UI 
//-----------------------------------------------------------------------------
VOID SetFileUI( HWND hDlg, TCHAR* strFileName )
{
    SetWindowText( GetDlgItem( hDlg, IDC_FILENAME), strFileName );
}



