/*
   MIDIデバイスへのメッセージ送信
     2004/ 2/ 6  宍戸 輝光
*/
#include <windows.h>
#include <mmsystem.h>

#pragma comment(lib, "winmm.lib")

HINSTANCE g_hInstance;
HWND g_hwMain;

HMIDIOUT g_hMidi;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    PSTR szCmdLine, int iCmdShow) {

	MSG  msg;
	WNDCLASS wndclass;

	g_hInstance = hInstance;

	/* ウインドウクラス設定 */
	wndclass.style         = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc   = WndProc;
	wndclass.cbClsExtra    = 0;
	wndclass.cbWndExtra    = 0;
	wndclass.hInstance     = hInstance;
	wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
	wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.lpszMenuName  = NULL;
	wndclass.lpszClassName = "MIDIMSG";

	RegisterClass(&wndclass);

	/* ウインドウ作成 */
	g_hwMain = CreateWindow("MIDIMSG", "MIDIデバイスへのメッセージ送信",
	            WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
	            CW_USEDEFAULT, CW_USEDEFAULT, 280, 96,
	            NULL, NULL, hInstance, NULL);

	/* ウインドウを表示 */
	ShowWindow(g_hwMain, iCmdShow);
	UpdateWindow(g_hwMain);

	/* メインループ */
	do {

		/* メッセージ処理 */
		if (GetMessage(&msg,NULL,0,0) == 0) {
			break;
		} else {

			TranslateMessage(&msg);
			DispatchMessage(&msg);

		}

	} while (TRUE);

	return (int)msg.wParam;

}

/* ウインドウプロシージャー */
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {

	HWND hwC, hwD;
	MIDIHDR mhMidi;

	/* GMリセット用データ */
	BYTE abyGMReset[] = {0xf0, 0x7e, 0x7f, 0x09, 0x01, 0xf7};

	switch (iMsg) {

	case WM_CREATE:

		/* MIDIデバイスオープン */
		if (midiOutOpen(&g_hMidi, MIDIMAPPER, 0, 0, 0) != MMSYSERR_NOERROR) {
			return 0;
		}

		ZeroMemory(&mhMidi, sizeof(mhMidi));

		/* GMリセット送信用バッファ設定 */
		mhMidi.lpData = (LPSTR)abyGMReset;
		mhMidi.dwBufferLength = 6;
		mhMidi.dwBytesRecorded = 6;

		midiOutPrepareHeader(g_hMidi, &mhMidi, sizeof(mhMidi));

		/* GMリセットメッセージ送信 */
		if (midiOutLongMsg(g_hMidi, &mhMidi, sizeof(mhMidi)) != MMSYSERR_NOERROR) {

			midiOutUnprepareHeader(g_hMidi, &mhMidi, sizeof(mhMidi));

			MessageBox(NULL, "MIDI音源の初期化に失敗しました。", "初期化失敗", MB_OK);

			midiOutClose(g_hMidi);

			return 0;

		}
	
		/* GMリセット完了待機 */
		while ((mhMidi.dwFlags & MHDR_DONE) == 0);

		midiOutUnprepareHeader(g_hMidi, &mhMidi, sizeof(mhMidi));

		/* チャネル1の音色をストリングスに設定 */
		midiOutShortMsg(g_hMidi, 0x000030c0);

		/* ボタン作成 */
		hwC = CreateWindow("BUTTON", "C", WS_CHILD|WS_VISIBLE,
		       4, 4, 28, 28, hwnd, (HMENU)0, g_hInstance, NULL);

		hwD = CreateWindow("BUTTON", "D", WS_CHILD|WS_VISIBLE,
		       40, 4, 28, 28, hwnd, (HMENU)1, g_hInstance, NULL);

		return 0;

	case WM_COMMAND:

		switch (LOWORD(wParam)) {

		case 0: /* o4C */

			midiOutShortMsg(g_hMidi, 0x00403c90);

			Sleep(500);

			midiOutShortMsg(g_hMidi, 0x00003c90);

			break;

		case 1: /* o4D */

			midiOutShortMsg(g_hMidi, 0x00403e90);

			Sleep(500);

			midiOutShortMsg(g_hMidi, 0x00003e90);

			break;

		}

		return 0;

	case WM_DESTROY: /* 終了処理 */

		midiOutReset(g_hMidi);
		midiOutClose(g_hMidi);

		PostQuitMessage(0);

		return 0;

	}

	return DefWindowProc (hwnd, iMsg, wParam, lParam) ;

}