Retired Document
Important: This sample code may not represent best practices for current development. The project may use deprecated symbols and illustrate technologies and techniques that are no longer recommended.
•QTMusic Sample Keyboards/EasyKeyboardDiagram.c
/* |
File: KeyboardDiagram.c |
Modified version from the one in the warhol project |
*/ |
#include <Memory.h> |
#include <QuickDraw.h> |
#include <Resources.h> |
#include "EasyKeyboardDiagram.h" |
static Handle GetAndDetachResource(ResType type,short id); |
#define kBlackKeyBottom 16 |
static Handle GetAndDetachResource(ResType type,short id) |
{ |
Handle h; |
h = GetResource(type,id); |
DetachResource(h); |
return h; |
} |
void InitializeKeyboard(KeyboardDiagram *kd,Rect *r,short octaveCount,short lowKey) |
{ |
short i; |
kd->r = *r; |
kd->octaveCount = octaveCount; |
kd->keyCount = octaveCount * 12; |
if(lowKey >= 128) |
{ |
kd->mod = true; |
kd->modOffset = ((lowKey + kd->keyCount - 1) / kd->keyCount) * kd->keyCount; |
lowKey &= 127; |
} |
else |
kd->mod = false; |
kd->lowKey = lowKey; |
for(i = 0; i < 128; i++) |
kd->keyVel[i] = 0; |
kd->whiteKey = (short **)GetAndDetachResource('Junk',kJunkWhite); |
kd->keyRight = (short **)GetAndDetachResource('Junk',kJunkBlack); |
} |
void TerminateKeyboard(KeyboardDiagram *kd) |
{ |
DisposeHandle((Handle)kd->whiteKey); |
DisposeHandle((Handle)kd->keyRight); |
} |
void SetKeyboardTopLeft(KeyboardDiagram *kd,short top, short left) |
{ |
OffsetRect(&kd->r, left - kd->r.left, top - kd->r.top); |
} |
void DrawKeyboardPiece(KeyboardDiagram *kd, short octave) |
{ |
Rect r; |
short w; |
PicHandle pH; |
PenNormal(); |
pH = (PicHandle)Get1Resource('PICT',kKeyboardPict); |
if(pH) |
{ |
r = (**pH).picFrame; |
w = r.right - r.left-1; |
OffsetRect(&r,kd->r.left - r.left + w * octave,kd->r.top - r.top); |
DrawPicture(pH,&r); |
if(kd->gray) |
{ |
GoGray(); |
PenMode(patBic); |
r.right += 2; |
r.bottom += 2; |
PaintRect(&r); |
PenNormal(); |
} |
} |
} |
void DrawKeyboardDropShadow(KeyboardDiagram *kd) |
{ |
MoveTo(kd->r.left + 3,kd->r.bottom); |
LineTo(kd->r.right,kd->r.bottom); |
LineTo(kd->r.right,kd->r.top + 3); |
} |
void DrawKeyboard(KeyboardDiagram *kd) |
{ |
short i; |
DrawKeyboardDropShadow(kd); |
for(i = 0; i < kd->octaveCount; i++) |
DrawKeyboardPiece(kd,i); |
} |
void SetKeyboardGray(KeyboardDiagram *kd,Boolean gray) |
{ |
if(kd->gray != gray) |
{ |
kd->gray = gray; |
DrawKeyboard(kd); |
} |
} |
void PaintKeyboardKey(KeyboardDiagram *kd,short pitch,short gray) |
/* |
* 0-255, gray; -1, invert; -2, forecolor |
*/ |
{ |
short i,k; |
short octave; |
Rect r1,r2; |
Boolean blackKey; |
if(kd->gray) |
goto goHome; |
r1.left = r1.right = 0; |
r2.left = r2.right = 0; |
pitch -= kd->lowKey; |
if(pitch < 0 || pitch >= kd->keyCount) |
goto goHome; |
octave = pitch / 12; |
pitch = pitch % 12; |
blackKey = false; |
if(pitch == 1 || pitch == 3 |
|| pitch == 6 || pitch == 8 || pitch == 10) |
{ |
/* |
* Black Keys |
*/ |
blackKey = true; |
r1.left = kd->r.left + (*kd->keyRight)[pitch - 1] + 2; |
r1.top = kd->r.top + 3; |
r1.right = kd->r.left + (*kd->keyRight)[pitch]; |
r1.bottom = kd->r.top + kBlackKeyBottom; |
} |
else |
{ |
/* |
* White Keys |
*/ |
k = kd->r.left + 2; |
i = 0; |
while((*kd->whiteKey)[i] != pitch) |
{ |
i++; |
k += 9; |
} |
r1.left = k; |
r1.top = kd->r.top + kBlackKeyBottom + 2; |
r1.right = k+6; |
r1.bottom = kd->r.bottom - 1; |
if(pitch) |
r2.left = kd->r.left + (*kd->keyRight)[pitch - 1] + 2; |
else |
r2.left = kd->r.left + 2; |
r2.top = kd->r.top + 2; |
r2.right = kd->r.left + (*kd->keyRight)[pitch]; |
r2.bottom = kd->r.top + kBlackKeyBottom + 2; |
/* |
* This is cheesy and proves I have |
* no idea what I am doing. - dvb |
*/ |
if(pitch == 5) |
r2.left ++; |
else if(pitch == 11) |
r2.right --; |
} |
OffsetRect(&r1,octave * 63,0); |
OffsetRect(&r2,octave * 63,0); |
if(gray >=0) |
{ |
RGBColor c; |
if(!blackKey) |
gray = 255 - gray; |
c.blue = c.green = c.red = (((unsigned short)gray)<<8) | gray; |
RGBForeColor(&c); |
} |
if(gray == -1) |
{ |
InvertRect(&r1); |
InvertRect(&r2); |
} |
else |
{ |
PaintRect(&r1); |
PaintRect(&r2); |
} |
goHome: |
ForeColor(blackColor); |
PenNormal(); |
} |
void PaintKeyboardVector(KeyboardDiagram *kd,unsigned char *keyVel) |
{ |
short i; |
unsigned char *w1,*w2; |
long x; |
w1 = keyVel; |
w2 = kd->keyVel; |
for(i = 0; i < 128; i++) |
{ |
x = *w1; |
if(*w2 != x) |
{ |
*w2 = x; |
x = x ? x+128:0; |
if( (i < kd->lowKey) || (i >= (kd->lowKey + kd->keyCount)) ) |
{ |
if(kd->mod) |
PaintKeyboardKey(kd, |
(i+kd->modOffset)%(kd->keyCount)+kd->lowKey,x); |
} |
PaintKeyboardKey(kd,i,x); |
} |
w1++; |
w2++; |
} |
} |
short GetKeyboardKey(KeyboardDiagram *kd,Point p) |
/* |
* Return -1 if outside rectangle. |
*/ |
{ |
short pitch,octave; |
if(PtInRect(p,&kd->r)) |
{ |
p.h -= kd->r.left; |
p.v -= kd->r.top; |
octave = p.h / 63; |
p.h %= 63; |
if(p.v > kBlackKeyBottom) |
pitch = (*kd->whiteKey)[p.h/9]; |
else |
{ |
pitch = 0; |
while((*kd->keyRight)[pitch] < p.h) |
pitch++; |
} |
pitch += octave*12; |
pitch += kd->lowKey; |
} |
else |
pitch = -1; |
return pitch; |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-03-19