PageRenderTime 47ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/Samples/Chap22/BachTocc/BachTocc.d

http://github.com/AndrejMitrovic/DWinProgramming
D | 194 lines | 153 code | 32 blank | 9 comment | 15 complexity | 376a7ddd7a18870b6c04f00cd877e73b MD5 | raw file
  1. /+
  2. + Copyright (c) Charles Petzold, 1998.
  3. + Ported to the D Programming Language by Andrej Mitrovic, 2011.
  4. +/
  5. module BachTocc;
  6. import core.memory;
  7. import core.runtime;
  8. import core.thread;
  9. import std.conv;
  10. import std.math;
  11. import std.range;
  12. import std.string;
  13. import std.utf;
  14. auto toUTF16z(S)(S s)
  15. {
  16. return toUTFz!(const(wchar)*)(s);
  17. }
  18. pragma(lib, "gdi32.lib");
  19. pragma(lib, "comdlg32.lib");
  20. pragma(lib, "winmm.lib");
  21. import core.sys.windows.windef;
  22. import core.sys.windows.winuser;
  23. import core.sys.windows.wingdi;
  24. import core.sys.windows.winbase;
  25. import core.sys.windows.commdlg;
  26. import core.sys.windows.mmsystem;
  27. string appName = "BachTocc";
  28. string description = "Bach Toccata in D Minor (First Bar)";
  29. HINSTANCE hinst;
  30. extern (Windows)
  31. int WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  32. {
  33. int result;
  34. try
  35. {
  36. Runtime.initialize();
  37. result = myWinMain(hInstance, hPrevInstance, lpCmdLine, iCmdShow);
  38. Runtime.terminate();
  39. }
  40. catch (Throwable o)
  41. {
  42. MessageBox(null, o.toString().toUTF16z, "Error", MB_OK | MB_ICONEXCLAMATION);
  43. result = 0;
  44. }
  45. return result;
  46. }
  47. int myWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int iCmdShow)
  48. {
  49. hinst = hInstance;
  50. HACCEL hAccel;
  51. HWND hwnd;
  52. MSG msg;
  53. WNDCLASS wndclass;
  54. wndclass.style = CS_HREDRAW | CS_VREDRAW;
  55. wndclass.lpfnWndProc = &WndProc;
  56. wndclass.cbClsExtra = 0;
  57. wndclass.cbWndExtra = 0;
  58. wndclass.hInstance = hInstance;
  59. wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  60. wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
  61. wndclass.hbrBackground = cast(HBRUSH)GetStockObject(WHITE_BRUSH);
  62. wndclass.lpszMenuName = appName.toUTF16z;
  63. wndclass.lpszClassName = appName.toUTF16z;
  64. if (!RegisterClass(&wndclass))
  65. {
  66. MessageBox(NULL, "This program requires Windows NT!", appName.toUTF16z, MB_ICONERROR);
  67. return 0;
  68. }
  69. MessageBox(null, "Reduce the volume on your speakers or in the volume control panel before you continue.", "Warning", MB_OK | MB_ICONWARNING);
  70. hwnd = CreateWindow(appName.toUTF16z, // window class name
  71. description.toUTF16z, // window caption
  72. WS_OVERLAPPEDWINDOW, // window style
  73. CW_USEDEFAULT, // initial x position
  74. CW_USEDEFAULT, // initial y position
  75. CW_USEDEFAULT, // initial x size
  76. CW_USEDEFAULT, // initial y size
  77. NULL, // parent window handle
  78. NULL, // window menu handle
  79. hInstance, // program instance handle
  80. NULL); // creation parameters
  81. ShowWindow(hwnd, iCmdShow);
  82. UpdateWindow(hwnd);
  83. while (GetMessage(&msg, NULL, 0, 0))
  84. {
  85. TranslateMessage(&msg);
  86. DispatchMessage(&msg);
  87. }
  88. return msg.wParam;
  89. }
  90. enum ID_TIMER = 1;
  91. DWORD MidiOutMessage(HMIDIOUT hMidi, int iStatus, int iChannel, int iData1, int iData2)
  92. {
  93. DWORD dwMessage = (iStatus | iChannel | (iData1 << 8) | (iData2 << 16));
  94. return midiOutShortMsg(hMidi, dwMessage);
  95. }
  96. extern (Windows)
  97. LRESULT WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) nothrow
  98. {
  99. scope (failure) assert(0);
  100. struct NoteSeq
  101. {
  102. int iDur;
  103. int[2] iNote;
  104. }
  105. enum noteseq = [NoteSeq(110, [69, 81]), NoteSeq(110, [67, 79]), NoteSeq(990, [69, 81]), NoteSeq(220, [-1, -1]),
  106. NoteSeq(110, [67, 79]), NoteSeq(110, [65, 77]), NoteSeq(110, [64, 76]), NoteSeq(110, [62, 74]),
  107. NoteSeq(220, [61, 73]), NoteSeq(440, [62, 74]), NoteSeq(1980, [-1, -1]), NoteSeq(110, [57, 69]),
  108. NoteSeq(110, [55, 67]), NoteSeq(990, [57, 69]), NoteSeq(220, [-1, -1]), NoteSeq(220, [52, 64]),
  109. NoteSeq(220, [53, 65]), NoteSeq(220, [49, 61]), NoteSeq(440, [50, 62]), NoteSeq(1980, [-1, -1])];
  110. static HMIDIOUT hMidiOut;
  111. static int iIndex;
  112. int i;
  113. switch (message)
  114. {
  115. case WM_CREATE:
  116. // Open MIDIMAPPER device
  117. if (midiOutOpen(&hMidiOut, MIDIMAPPER, 0, 0, 0))
  118. {
  119. MessageBeep(MB_ICONEXCLAMATION);
  120. MessageBox(hwnd, "Cannot open MIDI output device!",
  121. appName.toUTF16z, MB_ICONEXCLAMATION | MB_OK);
  122. return -1;
  123. }
  124. // Send Program Change messages for "Church Organ"
  125. MidiOutMessage(hMidiOut, 0xC0, 0, 19, 0);
  126. SetTimer(hwnd, ID_TIMER, 1000, NULL);
  127. return 0;
  128. case WM_TIMER:
  129. // Loop for 2-note polyphony
  130. for (i = 0; i < 2; i++)
  131. {
  132. // Note Off messages for previous note
  133. if (iIndex != 0 && noteseq[iIndex - 1].iNote[i] != -1)
  134. {
  135. MidiOutMessage(hMidiOut, 0x80, 0,
  136. noteseq[iIndex - 1].iNote[i], 0);
  137. }
  138. // Note On messages for new note
  139. if (iIndex != noteseq.length && noteseq[iIndex].iNote[i] != -1)
  140. {
  141. MidiOutMessage(hMidiOut, 0x90, 0, noteseq[iIndex].iNote[i], 127);
  142. }
  143. }
  144. if (iIndex != noteseq.length)
  145. {
  146. SetTimer(hwnd, ID_TIMER, noteseq[iIndex++].iDur - 1, NULL);
  147. }
  148. else
  149. {
  150. KillTimer(hwnd, ID_TIMER);
  151. DestroyWindow(hwnd);
  152. }
  153. return 0;
  154. case WM_DESTROY:
  155. midiOutReset(hMidiOut);
  156. midiOutClose(hMidiOut);
  157. PostQuitMessage(0);
  158. return 0;
  159. default:
  160. }
  161. return DefWindowProc(hwnd, message, wParam, lParam);
  162. }