|
|
1.1 ! root 1: /*-------------------------------------- ! 2: ORGAN.C -- Play Organ from Keyboard ! 3: --------------------------------------*/ ! 4: ! 5: #define INCL_DOS ! 6: #define INCL_WIN ! 7: #define INCL_GPI ! 8: #include <os2.h> ! 9: #include "organ.h" ! 10: ! 11: MRESULT EXPENTRY ClientWndProc (HWND, USHORT, MPARAM, MPARAM) ; ! 12: VOID EXPENTRY Speaker (USHORT usFreq) ; ! 13: ! 14: SHORT xOffset, yOffset, cxCaps, cyChar ; ! 15: USHORT usLastScan ; ! 16: ! 17: int main (void) ! 18: { ! 19: static CHAR szClientClass [] = "Organ" ; ! 20: static ULONG flFrameFlags = FCF_TITLEBAR | FCF_SYSMENU | ! 21: FCF_SIZEBORDER | FCF_MINMAX | ! 22: FCF_SHELLPOSITION | FCF_TASKLIST ; ! 23: HAB hab ; ! 24: HMQ hmq ; ! 25: HWND hwndFrame, hwndClient ; ! 26: QMSG qmsg ; ! 27: ! 28: if (DosPortAccess (0, 0, 0x42, 0x61)) // Don't run if port access fails ! 29: return 1 ; ! 30: ! 31: hab = WinInitialize (0) ; ! 32: hmq = WinCreateMsgQueue (hab, 0) ; ! 33: ! 34: WinRegisterClass (hab, szClientClass, ClientWndProc, CS_SIZEREDRAW, 0) ; ! 35: ! 36: hwndFrame = WinCreateStdWindow (HWND_DESKTOP, WS_VISIBLE, ! 37: &flFrameFlags, szClientClass, NULL, ! 38: 0L, NULL, 0, &hwndClient) ; ! 39: ! 40: WinSendMsg (hwndFrame, WM_SETICON, ! 41: WinQuerySysPointer (HWND_DESKTOP, SPTR_APPICON, FALSE), ! 42: NULL) ; ! 43: ! 44: while (WinGetMsg (hab, &qmsg, NULL, 0, 0)) ! 45: WinDispatchMsg (hab, &qmsg) ; ! 46: ! 47: WinDestroyWindow (hwndFrame) ; ! 48: WinDestroyMsgQueue (hmq) ; ! 49: WinTerminate (hab) ; ! 50: DosPortAccess (0, 1, 0x42, 0x61) ; ! 51: return 0 ; ! 52: } ! 53: ! 54: VOID DrawKey (HPS hps, USHORT usScanCode, BOOL fInvert) ! 55: { ! 56: RECTL rcl ; ! 57: ! 58: rcl.xLeft = 3 * cxCaps * key[usScanCode].xPos / 2 + xOffset ; ! 59: rcl.yBottom = 3 * cyChar * key[usScanCode].yPos / 2 + yOffset ; ! 60: rcl.xRight = rcl.xLeft + 3 * cxCaps ; ! 61: rcl.yTop = rcl.yBottom + 3 * cyChar / 2 ; ! 62: ! 63: WinDrawText (hps, -1, key[usScanCode].szKey, &rcl, ! 64: CLR_NEUTRAL, CLR_BACKGROUND, ! 65: DT_CENTER | DT_VCENTER | DT_ERASERECT) ; ! 66: if (fInvert) ! 67: WinInvertRect (hps, &rcl) ; ! 68: ! 69: WinDrawBorder (hps, &rcl, 1, 1, CLR_NEUTRAL, CLR_BACKGROUND, ! 70: DB_STANDARD) ; ! 71: } ! 72: ! 73: VOID ProcessKey (HPS hps, USHORT usScanCode, USHORT fsFlags) ! 74: { ! 75: static USHORT ausOctFreq [] = { 262, 277, 294, 311, 330, 349, ! 76: 370, 392, 415, 440, 466, 494 } ; ! 77: USHORT usOct, usFreq ; ! 78: ! 79: if (usScanCode >= NUMSCANS) // No scan codes over 53 ! 80: return ; ! 81: if ((usOct = key[usScanCode].sOctave) == -1) // Non-music key ! 82: return ; ! 83: ! 84: if (fsFlags & KC_KEYUP) // For key up ! 85: { ! 86: if (usLastScan == usScanCode) // If that's the note ! 87: { ! 88: Speaker (0) ; // turn off speaker ! 89: DrawKey (hps, usScanCode, FALSE) ; // and redraw key ! 90: usLastScan = 0 ; ! 91: } ! 92: return ; ! 93: } ! 94: if (fsFlags & KC_PREVDOWN) // Ignore typematics ! 95: return ; ! 96: ! 97: usFreq = ausOctFreq [key[usScanCode].sNote] ; // Get frequency ! 98: ! 99: if (fsFlags & KC_SHIFT) ! 100: usOct += fsFlags & KC_ALT ? 2 : 1 ; // Higher octave ! 101: else if (fsFlags & KC_CTRL) ! 102: usOct -= fsFlags & KC_ALT ? 2 : 1 ; // Lower octave ! 103: ! 104: if (usOct > 4) // Shift frequency ! 105: usFreq <<= (usOct - 4) ; // for octave ! 106: else if (usOct < 4) ! 107: usFreq >>= (4 - usOct) ; ! 108: ! 109: Speaker (usFreq) ; // Turn on speaker ! 110: DrawKey (hps, usScanCode, TRUE) ; // Draw the inverted key ! 111: ! 112: if (usLastScan != 0) ! 113: DrawKey (hps, usLastScan, FALSE) ; // Redraw previous key ! 114: usLastScan = usScanCode ; // Save scan code ! 115: } ! 116: ! 117: MRESULT EXPENTRY ClientWndProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2) ! 118: { ! 119: FONTMETRICS fm ; ! 120: HPS hps ; ! 121: SHORT cxClient, cyClient ; ! 122: USHORT usScanCode ; ! 123: ! 124: switch (msg) ! 125: { ! 126: case WM_CREATE: ! 127: hps = WinGetPS (hwnd) ; ! 128: GpiQueryFontMetrics (hps, (LONG) sizeof fm, &fm) ; ! 129: cxCaps = (SHORT) fm.lEmInc ; ! 130: cyChar = (SHORT) fm.lMaxBaselineExt ; ! 131: WinReleasePS (hps) ; ! 132: return 0 ; ! 133: ! 134: case WM_SIZE: ! 135: cxClient = SHORT1FROMMP (mp2) ; ! 136: cyClient = SHORT2FROMMP (mp2) ; ! 137: ! 138: xOffset = (cxClient - 25 * 3 * cxCaps / 2) / 2 ; ! 139: yOffset = (cyClient - 6 * cyChar) / 2 ; ! 140: return 0 ; ! 141: ! 142: case WM_CHAR: ! 143: if (!(CHARMSG(&msg)->fs & KC_SCANCODE)) ! 144: break ; ! 145: ! 146: hps = WinGetPS (hwnd) ; ! 147: ProcessKey (hps, CHARMSG(&msg)->scancode, CHARMSG(&msg)->fs) ; ! 148: WinReleasePS (hps) ; ! 149: return 0 ; ! 150: ! 151: case WM_PAINT: ! 152: hps = WinBeginPaint (hwnd, NULL, NULL) ; ! 153: GpiErase (hps) ; ! 154: ! 155: for (usScanCode = 0 ; usScanCode < NUMSCANS ; usScanCode++) ! 156: if (key[usScanCode].xPos != -1) ! 157: DrawKey (hps, usScanCode, usScanCode == usLastScan) ; ! 158: ! 159: WinEndPaint (hps) ; ! 160: return 0 ; ! 161: } ! 162: return WinDefWindowProc (hwnd, msg, mp1, mp2) ; ! 163: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.