|
|
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.