//////////////////////////////////////////////////////////////////
// File - speaker_gui.c
//
// This application plays a tone to the speaker, and is
// controlled via a graphical user interface.
// The speaker is accessed directly on the motherboard, using
// WinDriver functions.
// 
//////////////////////////////////////////////////////////////////

#include <windows.h>
#include "resource.h"
#include "../speaker/speaker_lib.h"
#include <stdio.h>


BOOL InitApplication( HANDLE hInstance );
HWND InitInstance( HANDLE hInstance, int nCmdShow );
LRESULT PASCAL SpeakerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam );
VOID GoModalDialogBoxParam( HINSTANCE hInstance, LPCSTR lpszTemplate, HWND hWnd, DLGPROC lpDlgProc, LPARAM lParam );
BOOL PASCAL ToneDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );
BOOL PASCAL AboutDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam );

char gszAppName[] = "Speaker";
char gszSpeakerClass[] = "SpeakerWndClass";
SPEAKER_HANDLE hSpeaker = NULL;


// The main window loop.
// WinMain() opens a handle for speaker, and then creates the main menu window.
int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszCmdLine, int nCmdShow )
{
    HWND hSpeakerWnd;
    MSG msg;

    if (!hPrevInstance)
        if (!InitApplication( hInstance ))
            return FALSE;

    if (!SPEAKER_Open(&hSpeaker))
    {
        char msg[256];
        sprintf (msg, "Error while opening speaker hardware:\n%s", SPEAKER_ErrorString);
        MessageBox( NULL, msg, "Speaker Sample", MB_OK | MB_ICONERROR );
        return FALSE;
    }

    if (NULL == (hSpeakerWnd = InitInstance( hInstance, nCmdShow )))
        return FALSE;

    while (GetMessage( &msg, NULL, 0, 0 ))
    {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }

    SPEAKER_Close (hSpeaker);

    return (int) msg.wParam;
} 

// Initilization. This registers information such as window classes.
BOOL InitApplication( HANDLE hInstance )
{
    WNDCLASS  wndclass;

    // register Speaker window class
    wndclass.style =         0;
    wndclass.lpfnWndProc =   SpeakerWndProc;
    wndclass.cbClsExtra =    0;
    wndclass.cbWndExtra =    0;
    wndclass.hInstance =     hInstance;
    wndclass.hIcon =         LoadIcon( hInstance, MAKEINTRESOURCE( SPEAKERICON ) );
    wndclass.hCursor =       LoadCursor( NULL, IDC_ARROW );
    wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
    wndclass.lpszMenuName =  MAKEINTRESOURCE( SPEAKERMENU );
    wndclass.lpszClassName = gszSpeakerClass;

    return RegisterClass( &wndclass );
}

// Initializes instance specific information.
HWND InitInstance( HANDLE hInstance, int nCmdShow )
{
    HWND hSpeakerWnd;

    // create the Speaker window
    hSpeakerWnd = CreateWindow( gszSpeakerClass, gszAppName,
                           WS_OVERLAPPEDWINDOW,
                           CW_USEDEFAULT, CW_USEDEFAULT,
                           CW_USEDEFAULT, CW_USEDEFAULT,
                           NULL, NULL, hInstance, NULL );

    if (NULL == hSpeakerWnd)
        return NULL;

    ShowWindow( hSpeakerWnd, nCmdShow );
    UpdateWindow( hSpeakerWnd );

    return hSpeakerWnd;
}

// This is the Speaker main menu Window Proc.
LRESULT PASCAL SpeakerWndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    switch (uMsg)
    {
    case WM_COMMAND:
        switch ( LOWORD( wParam ) )
        {
        case IDM_CHIMES:
           SPEAKER_Tone(hSpeaker, 440, 400);
           SPEAKER_Tone(hSpeaker, 329, 200);
           SPEAKER_Tone(hSpeaker, 1, 10);
           SPEAKER_Tone(hSpeaker, 329, 200);
           SPEAKER_Tone(hSpeaker, 369, 400);
           SPEAKER_Tone(hSpeaker, 329, 800);
           SPEAKER_Tone(hSpeaker, 415, 400);
           SPEAKER_Tone(hSpeaker, 440, 600);
           break;

        case IDM_TONE:
            GoModalDialogBoxParam( (HINSTANCE) GetWindowLong( hWnd, GWL_HINSTANCE ),
                                  MAKEINTRESOURCE( PLAYTONEDLGBOX ), hWnd,
                                  ToneDlgProc,
                                  (LPARAM) NULL);

            break;

        case IDM_ABOUT:
            GoModalDialogBoxParam ( (HINSTANCE) GetWindowLong( hWnd, GWL_HINSTANCE ),
                                   MAKEINTRESOURCE( ABOUTDLGBOX ),
                                   hWnd,
                                   AboutDlgProc, 0L );
            break;

        case IDM_EXIT:
            PostMessage( hWnd, WM_CLOSE, 0, 0L );
            break;
        }
        break;

    case WM_DESTROY:
        PostQuitMessage( 0 );
        break;

    default:
        return DefWindowProc( hWnd, uMsg, wParam, lParam );
    }

    return FALSE;
} 

// This is the About dialog Window Proc.
BOOL PASCAL AboutDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
        return TRUE;

    case WM_COMMAND:
        if (LOWORD( wParam ) == IDD_OK)
        {
            EndDialog( hDlg, TRUE );
            return TRUE;
        }
        break;
    }
    return FALSE;
}

// This is the Speaker Play Tone dialog Window Proc.
BOOL PASCAL ToneDlgProc( HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam )
{
    switch (uMsg)
    {
    case WM_INITDIALOG:
        SetDlgItemText( hDlg, IDC_FREQ, "440");
        SetDlgItemText( hDlg, IDC_DURATION, "1000");
        return TRUE;

    case WM_COMMAND:
        switch ( LOWORD( wParam ))
        {
        case IDD_PLAY_TONE:
            {
                DWORD dwHertz = GetDlgItemInt(hDlg, IDC_FREQ, NULL, FALSE);
                DWORD dwMilli = GetDlgItemInt(hDlg, IDC_DURATION, NULL, FALSE);
                if (dwHertz && dwMilli) 
                    SPEAKER_Tone(hSpeaker, dwHertz, dwMilli);
                break;
            } 

        case IDD_CLOSE:
            EndDialog( hDlg, TRUE );
            return TRUE;
        }
        break;
    }

    return FALSE;
}

VOID GoModalDialogBoxParam( HINSTANCE hInstance, LPCSTR lpszTemplate, HWND hWnd, DLGPROC lpDlgProc, LPARAM lParam )
{
    DLGPROC  lpProcInstance;

    lpProcInstance = (DLGPROC) MakeProcInstance( (FARPROC) lpDlgProc, hInstance );
    DialogBoxParam( hInstance, lpszTemplate, hWnd, lpProcInstance, lParam );
    FreeProcInstance( (FARPROC) lpProcInstance );
}