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.
GiMeDaPalette&Sound.c
/* |
File: GiMeDaPalette&Sound.c |
Contains: This is the original version of GiMeDaPalette with the change to it to make it |
possible to play a sound at the same time as the colors are being animated. |
The method which is being used to play the sound is to use Double Buffering. |
When ever you select some form of Animation from the menu, there will be sound |
to go with it. |
Written by: RICHARD P. COLLYER |
Copyright: Copyright © 1990-1999 by Apple Computer, Inc., All Rights Reserved. |
You may incorporate this Apple sample source code into your program(s) without |
restriction. This Apple sample source code has been provided "AS IS" and the |
responsibility for its operation is yours. You are not permitted to redistribute |
this Apple sample source code as "Apple sample source code" after having made |
changes. If you're going to re-distribute the source, we require that you make |
it clear in the source that the code was descended from Apple sample source |
code, but that you've made changes. |
Change History (most recent first): |
8/2/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1 |
*/ |
#include <CType.h> |
#include <Quickdraw.h> |
#include <Windows.h> |
#include <desk.h> |
#include <dialogs.h> |
#include <Events.h> |
#include <GestaltEqu.h> |
#include <Memory.h> |
#include <Menus.h> |
#include <OSEvents.h> |
#include <Palettes.h> |
#include <SegLoad.h> |
#include <Sound.h> |
#include <Resources.h> |
#include <ToolUtils.h> |
#include <StdIO.h> |
#include <QDOffscreen.h> |
extern _DataInit(); |
#define pmInhibitG2 0x0100 |
#define pmInhibitC2 0x0200 |
#define pmInhibitG4 0x0400 |
#define pmInhibitC4 0x0800 |
#define pmInhibitG8 0x1000 |
#define pmInhibitC8 0x2000 |
#define TRUE 0xFF |
#define FALSE 0 |
#define Gestalttest 0xA1AD |
#define NoTrap 0xA89F |
#define appleID 128 |
#define appleMenu 0 |
#define aboutMeCommand 1 |
#define fileID 129 |
#define quitCommand 1 |
#define PaletteID 130 |
#define CourCommand 1 |
#define TolCommand 2 |
#define ExpCommand 3 |
#define AniCommand 4 |
#define TolExpCommand 6 |
#define TolAniCommand 7 |
#define ExpAniCommand 8 |
#define TEACommand 10 |
#define PictID 128 |
#define clutID 150 |
#define aboutMeDLOG 128 |
#define okButton 1 |
#define authorItem 2 |
#define languageItem 3 |
#define numcolor 256 |
#define kDoubleBufferSize 0x1000 |
struct LocalVars { |
long bytesTotal; |
long bytesCopied; |
Ptr dataPtr; |
}; |
typedef struct LocalVars LocalVars; |
typedef LocalVars *LocalVarsPtr; |
Rect TotalRect, minRect, WinMinusScroll, InitWindowSize; |
WindowPtr myWindow; |
CTabHandle mycolors; |
PaletteHandle srcPalette; |
Boolean DoneFlag; |
MenuHandle mymenu1, mymenu2, mymenu0; |
PicHandle ThePict; |
GWorldPtr offscreenGWorld; |
SndDoubleBufferHeader doubleHeader; |
SndDoubleBufferPtr doubleBuffer; |
SCStatus Stats; |
SndChannelPtr chan; |
SoundHeaderPtr Head; |
Handle SoundData; |
LocalVars myVars; |
SndDoubleBackUPP gSndDoubleBackUPP; |
pascal void MyDoubleBackProc (SndChannelPtr channel, SndDoubleBufferPtr doubleBufferPtr); |
void CheckMenu(int whichMenu); |
void SoundSetUp(); |
void SoundOff(); |
void Draw(); |
void SetInhibited(int Usage); |
void showAboutMeDialog(); |
void doCommand(long mResult); |
void init(); |
/*______________________________________________________*/ |
/* Sound Double Back Proc */ |
/*______________________________________________________*/ |
pascal void MyDoubleBackProc (SndChannelPtr chan,SndDoubleBufferPtr doubleBuffer) |
{ |
#pragma unused(chan) |
LocalVarsPtr myVarsPtr; |
long bytesToCopy; |
myVarsPtr = (LocalVarsPtr) doubleBuffer->dbUserInfo[0]; |
bytesToCopy = myVarsPtr->bytesTotal - myVarsPtr->bytesCopied; |
if (bytesToCopy > kDoubleBufferSize) |
bytesToCopy = kDoubleBufferSize; |
BlockMove (myVarsPtr->dataPtr, &doubleBuffer->dbSoundData[0], bytesToCopy); |
doubleBuffer->dbNumFrames = bytesToCopy; |
doubleBuffer->dbFlags = (doubleBuffer->dbFlags) | dbBufferReady; |
myVarsPtr->dataPtr = (Ptr) ((myVarsPtr->dataPtr) + bytesToCopy); |
myVarsPtr->bytesCopied = myVarsPtr->bytesCopied + bytesToCopy; |
if (myVarsPtr->bytesCopied == myVarsPtr->bytesTotal) { |
doubleBuffer->dbFlags = (doubleBuffer->dbFlags) | dbLastBuffer; |
} |
return; |
} |
/*______________________________________________________*/ |
/* Check Correct Menu */ |
/*______________________________________________________*/ |
void CheckMenu(int whichMenu) |
/* This procedure checks and unchecks the appropriate menus */ |
{ |
CheckItem(mymenu2,CourCommand,FALSE); |
CheckItem(mymenu2,TolCommand,FALSE); |
CheckItem(mymenu2,ExpCommand,FALSE); |
CheckItem(mymenu2,AniCommand,FALSE); |
CheckItem(mymenu2,TolExpCommand,FALSE); |
CheckItem(mymenu2,TolAniCommand,FALSE); |
CheckItem(mymenu2,ExpAniCommand,FALSE); |
CheckItem(mymenu2,TEACommand,FALSE); |
switch (whichMenu) { |
case CourCommand: |
CheckItem(mymenu2,CourCommand,TRUE); |
break; |
case TolCommand: |
CheckItem(mymenu2,TolCommand,TRUE); |
break; |
case ExpCommand: |
CheckItem(mymenu2,ExpCommand,TRUE); |
break; |
case AniCommand: |
CheckItem(mymenu2,AniCommand,TRUE); |
break; |
case TolExpCommand: |
CheckItem(mymenu2,TolExpCommand,TRUE); |
break; |
case TolAniCommand: |
CheckItem(mymenu2,TolAniCommand,TRUE); |
break; |
case ExpAniCommand: |
CheckItem(mymenu2,ExpAniCommand,TRUE); |
break; |
case TEACommand: |
CheckItem(mymenu2,TEACommand,TRUE); |
break; |
defalut: |
break; |
} |
} |
/*______________________________________________________*/ |
/* Start Sound */ |
/*______________________________________________________*/ |
void SoundSetUp() |
{ |
int i; |
OSErr err; |
chan = nil; |
err = SndNewChannel (&chan, sampledSynth, 0, nil); |
if (err != noErr) |
Debugger(); |
Head = (SoundHeaderPtr) NewPtrClear (sizeof(SoundHeader)); |
Head->samplePtr = *SoundData; |
Head->length = 45838; |
Head->sampleRate = 0x56EE8BA3; //recorded at 22KHz |
Head->loopStart = 0; |
Head->loopEnd = 0; |
Head->encode = 0; |
Head->baseFrequency = 60; |
Head->sampleArea[0] = 0; |
myVars.bytesTotal = Head->length; |
myVars.bytesCopied = 0; |
myVars.dataPtr = Head->samplePtr; |
doubleHeader.dbhNumChannels = 1; |
doubleHeader.dbhSampleSize = 8; |
doubleHeader.dbhCompressionID = 0; |
doubleHeader.dbhPacketSize = 0; |
doubleHeader.dbhSampleRate = Head->sampleRate; |
doubleHeader.dbhDoubleBack = gSndDoubleBackUPP; |
for (i = 0; i <= 1; ++i) { |
doubleBuffer = (SndDoubleBufferPtr) NewPtrClear (sizeof(SndDoubleBuffer) + kDoubleBufferSize); |
if (doubleBuffer == nil || MemError() != 0) |
Debugger(); |
doubleBuffer->dbNumFrames = 0; |
doubleBuffer->dbFlags = 0; |
doubleBuffer->dbUserInfo [0] = (long) &myVars; |
MyDoubleBackProc (chan, doubleBuffer); // initialize the buffers |
doubleHeader.dbhBufferPtr [i] = doubleBuffer; |
} |
} |
/*______________________________________________________*/ |
/* Start Sound */ |
/*______________________________________________________*/ |
void SoundOff() |
{ |
OSErr err; |
err = SndPlayDoubleBuffer (chan, &doubleHeader); |
if (err != noErr) |
Debugger(); |
} |
/*______________________________________________________*/ |
/* Set Up Usage of Palette */ |
/*______________________________________________________*/ |
void Draw() |
{ |
RGBColor black = {0,0,0}, White = {65535,65535,65535}; |
RGBForeColor (&black); |
RGBBackColor (&White); |
CopyBits ((BitMap *) *offscreenGWorld->portPixMap, &myWindow->portBits, |
&InitWindowSize, &WinMinusScroll, srcCopy, nil); |
} |
/*______________________________________________________*/ |
/* Set Up Usage of Palette */ |
/*______________________________________________________*/ |
void SetInhibited(int Usage) |
/* When the usage of the palette changes I need to rebuild the palette, |
so I call this routine. I need to call SetEntryUsage on all of the entries |
of the palette, but I want to make sure that if the monitor is set to a bit depth |
low than 8 bits that the palette is limited in its colors. So the first two colors |
(not including white) are set to work at all depths except 1 bit mode. The next |
12 entries are set to work on all depths except 1 & 2 bit modes. The rest of |
the colors are set to only work in 8 bit mode. I have also set the tolerance to |
hex 1500. With this tolerance I will be able to get most of the colors I need |
and those that I don't get exact will be very close. */ |
{ |
int i; |
CTab2Palette (mycolors, srcPalette, Usage, 0x1500); |
for (i = 1; i <= 2; ++i) { |
SetEntryUsage (srcPalette, i, Usage, 0x1500); |
} |
for (i = 3; i <= 14; ++i) { |
SetEntryUsage (srcPalette, i, Usage+pmInhibitG2+pmInhibitC2, 0x1500); |
} |
for (i = 15; i < numcolor; ++i) { |
SetEntryUsage (srcPalette, i, Usage+pmInhibitG2+pmInhibitC2+ |
pmInhibitG4+pmInhibitC4, 0x1500); |
} |
} |
/*______________________________________________________*/ |
/* About Prog Dialog */ |
/*______________________________________________________*/ |
void showAboutMeDialog() |
{ |
GrafPtr savePort; |
DialogPtr theDialog; |
short itemHit; |
GetPort(&savePort); |
theDialog = GetNewDialog(aboutMeDLOG, nil, (WindowPtr) -1); |
SetPort(theDialog); |
do { |
ModalDialog(nil, &itemHit); |
} while (itemHit != okButton); |
CloseDialog(theDialog); |
SetPort(savePort); |
return; |
} |
/*______________________________________________________*/ |
/* Do Menu Function */ |
/*______________________________________________________*/ |
void doCommand(long mResult) |
{ |
int theMenu, theItem; |
Str255 daName; |
GrafPtr savePort; |
theItem = LoWord(mResult); |
theMenu = HiWord(mResult); |
switch (theMenu) { |
/*______________________________________________________*/ |
/* Do Apple Menu */ |
/*______________________________________________________*/ |
case appleID: |
if (theItem == aboutMeCommand) |
showAboutMeDialog(); |
else { |
GetMenuItemText(mymenu0, theItem, daName); |
GetPort(&savePort); |
(void) OpenDeskAcc(daName); |
SetPort(savePort); |
} |
break; |
/*______________________________________________________*/ |
/* Do File Menu */ |
/*______________________________________________________*/ |
case fileID: |
switch (theItem) { |
case quitCommand: |
DoneFlag = TRUE; |
break; |
default: |
break; |
} |
break; |
/*______________________________________________________*/ |
/* Do File Menu */ |
/*______________________________________________________*/ |
case PaletteID: |
switch (theItem) { |
case CourCommand: |
CheckMenu(CourCommand); |
SetInhibited(pmCourteous); |
break; |
case TolCommand: |
CheckMenu(TolCommand); |
SetInhibited(pmTolerant); |
break; |
case ExpCommand: |
CheckMenu(ExpCommand); |
SetInhibited(pmExplicit); |
break; |
case AniCommand: |
CheckMenu(AniCommand); |
SetInhibited(pmAnimated); |
SoundOff(); |
break; |
case TolExpCommand: |
CheckMenu(TolExpCommand); |
SetInhibited(pmTolerant+pmExplicit); |
break; |
case TolAniCommand: |
CheckMenu(TolAniCommand); |
SetInhibited(pmTolerant+pmAnimated); |
SoundOff(); |
break; |
case ExpAniCommand: |
CheckMenu(ExpAniCommand); |
SetInhibited(pmAnimated+pmExplicit); |
SoundOff(); |
break; |
case TEACommand: |
CheckMenu(TEACommand); |
SetInhibited(pmTolerant+pmExplicit+pmAnimated); |
SoundOff(); |
break; |
default: |
break; |
} |
SetPalette ((WindowPtr) myWindow, srcPalette, TRUE); |
ActivatePalette ((WindowPtr) myWindow); |
break; |
} |
HiliteMenu(0); |
return; |
} |
/*______________________________________________________*/ |
/* Initialization traps */ |
/*______________________________________________________*/ |
void init() |
{ |
RgnHandle tempRgn; |
Rect BaseRect; |
OSErr err; |
long QDfeature, OSfeature; |
GDHandle SaveGD; |
CGrafPtr SavePort; |
RGBColor black = {0,0,0}, White = {65535,65535,65535}; |
//UnloadSeg(_DataInit); |
InitGraf(&qd.thePort); |
FlushEvents(everyEvent, 0); |
InitMenus(); |
InitWindows(); |
InitDialogs(nil); |
InitCursor(); |
/* set up the UPP for MyDoubleBackProc */ |
gSndDoubleBackUPP = NewSndDoubleBackProc(MyDoubleBackProc); |
DoneFlag = FALSE; |
ThePict = GetPicture(PictID); |
if (ThePict == nil) |
DoneFlag = TRUE; |
/*______________________________________________________*/ |
/* Use Gestalt to find 32BQD */ |
/*______________________________________________________*/ |
err = Gestalt(gestaltQuickdrawVersion, &QDfeature); |
if (err && (QDfeature & 0x0f00) < 0x0200) |
DoneFlag = TRUE; |
err = Gestalt(gestaltSystemVersion, &OSfeature); |
if (err) |
DoneFlag = TRUE; |
if (!DoneFlag && (QDfeature & 0x0f00) != 0x0200 && OSfeature < 0x0605) |
DoneFlag = TRUE; |
/*______________________________________________________*/ |
/* Set Rects */ |
/*______________________________________________________*/ |
if (DoneFlag == FALSE) { |
SetRect(&BaseRect, 40, 60, 472, 282); |
SetRect(&WinMinusScroll, BaseRect.left-40, BaseRect.top-60, BaseRect.right-60, |
BaseRect.bottom - 80); |
SetRect(&InitWindowSize, WinMinusScroll.left, WinMinusScroll.top, |
WinMinusScroll.right, WinMinusScroll.bottom); |
tempRgn = GetGrayRgn(); |
HLock ((Handle) tempRgn); |
TotalRect = (**tempRgn).rgnBBox; |
SetRect(&minRect, 80, 80, (**tempRgn).rgnBBox.right - 40, |
(**tempRgn).rgnBBox.bottom - 40); |
HUnlock ((Handle) tempRgn); |
/*______________________________________________________*/ |
/* Open Window & set Palette & Picture */ |
/*______________________________________________________*/ |
GetGWorld (&SavePort, &SaveGD); |
mycolors = GetCTable (clutID); |
(*mycolors)->ctFlags |= 0x4000; |
myWindow = NewCWindow(nil, &BaseRect, "\p", TRUE, zoomDocProc, |
(WindowPtr) -1, TRUE, 150); |
SetGWorld((CGrafPtr)myWindow, SaveGD); |
DrawGrowIcon (myWindow); |
srcPalette = NewPalette (numcolor, mycolors, pmCourteous, 0); |
SetInhibited(pmCourteous); |
SetPalette ((WindowPtr) myWindow, srcPalette, TRUE); |
DrawPicture (ThePict, &InitWindowSize); |
GetGWorld (&SavePort, &SaveGD); |
err = NewGWorld (&offscreenGWorld, 8, &InitWindowSize, mycolors, nil, nil); |
if (err) |
Debugger(); |
SetGWorld (offscreenGWorld, nil); |
EraseRect (&InitWindowSize); |
DrawPicture (ThePict, &InitWindowSize); |
SetGWorld (SavePort, SaveGD); |
/*______________________________________________________*/ |
/* Set menus */ |
/*______________________________________________________*/ |
mymenu0 = GetMenu(appleID); |
AppendResMenu(mymenu0, 'DRVR'); |
InsertMenu(mymenu0,0); |
mymenu1 = GetMenu(129); |
InsertMenu(mymenu1,0); |
mymenu2 = GetMenu(130); |
InsertMenu(mymenu2,0); |
DrawMenuBar(); |
/*______________________________________________________*/ |
/* Set Up Sound */ |
/*______________________________________________________*/ |
SoundData = GetResource ('snd ', 100); |
if (ResError() != noErr || SoundData == nil) |
Debugger(); |
HLock (SoundData); |
SoundSetUp(); |
} |
return; |
} |
main() |
{ |
char key; |
Boolean track; |
long growResult; |
EventRecord myEvent; |
WindowPtr whichWindow; |
int yieldTime; |
RGBColor changecolor; |
CTabHandle StoreCTab; |
short Usage, Tolerance; |
OSErr err; |
/*______________________________________________________*/ |
/* Main Event loop */ |
/*______________________________________________________*/ |
init(); |
yieldTime = 0; |
StoreCTab = GetCTable (clutID); |
for ( ;; ) { |
if (DoneFlag) { |
ExitToShell(); |
} |
/* If the usage is set to animate than animate the colors one step for eash event loop */ |
GetEntryUsage(srcPalette, 1, &Usage, &Tolerance); |
Usage &= 0x0004; |
if (Usage == 0x0004) { |
err = SndChannelStatus (chan, sizeof (Stats), &Stats); |
if (err != noErr) |
Debugger(); |
if (!Stats.scChannelBusy) { |
err = SndDisposeChannel (chan,FALSE); |
if (err != noErr) |
Debugger(); |
SoundSetUp(); |
SoundOff(); |
} |
GetEntryColor (srcPalette, 1, &changecolor); |
AnimatePalette (myWindow, StoreCTab, 2, 1, numcolor - 2); |
AnimateEntry (myWindow, numcolor - 1, &changecolor); |
Palette2CTab (srcPalette, StoreCTab); |
} |
if (WaitNextEvent(everyEvent, &myEvent, yieldTime, nil)) { |
switch (myEvent.what) { |
case mouseDown: |
switch (FindWindow(myEvent.where, &whichWindow)) { |
case inSysWindow: |
SystemClick(&myEvent, whichWindow); |
break; |
case inMenuBar: |
doCommand(MenuSelect(myEvent.where)); |
break; |
case inContent: |
break; |
case inDrag: |
DragWindow (whichWindow, myEvent.where, &TotalRect); |
Draw(); |
DrawGrowIcon (whichWindow); |
break; |
case inGrow: |
growResult = GrowWindow (whichWindow, myEvent.where, |
&minRect); |
SizeWindow(whichWindow, LoWord(growResult), |
HiWord(growResult), TRUE); |
EraseRect(&whichWindow->portRect); |
SetRect(&WinMinusScroll, whichWindow->portRect.left, |
whichWindow->portRect.top, |
whichWindow->portRect.right-20, |
whichWindow->portRect.bottom - 20); |
Draw(); |
DrawGrowIcon (whichWindow); |
break; |
case inGoAway: |
track = TrackGoAway (whichWindow, myEvent.where); |
if (track) { |
CloseWindow (whichWindow); |
DoneFlag = TRUE; |
} |
break; |
case inZoomIn: |
track = TrackBox (whichWindow, myEvent.where, inZoomIn); |
if (track) { |
ZoomWindow (whichWindow, inZoomIn, TRUE); |
EraseRect(&whichWindow->portRect); |
SetRect(&WinMinusScroll, whichWindow->portRect.left, |
whichWindow->portRect.top, |
whichWindow->portRect.right-20, |
whichWindow->portRect.bottom - 20); |
Draw(); |
DrawGrowIcon (whichWindow); |
} |
break; |
case inZoomOut: |
track = TrackBox (whichWindow, myEvent.where, inZoomOut); |
if (track) { |
ZoomWindow (whichWindow, inZoomOut, TRUE); |
EraseRect(&whichWindow->portRect); |
SetRect(&WinMinusScroll, whichWindow->portRect.left, |
whichWindow->portRect.top, |
whichWindow->portRect.right-20, |
whichWindow->portRect.bottom - 20); |
Draw(); |
DrawGrowIcon (whichWindow); |
} |
break; |
default: |
break; |
} |
break; |
case keyDown: |
case autoKey: |
key = myEvent.message & charCodeMask; |
if ( myEvent.modifiers & cmdKey ) |
if ( myEvent.what == keyDown ) |
doCommand(MenuKey(key)); |
break; |
case updateEvt: |
if ((WindowPtr) myEvent.message == myWindow) { |
BeginUpdate((WindowPtr) myWindow); |
EndUpdate((WindowPtr) myWindow); |
Draw(); |
} |
break; |
case diskEvt: |
break; |
case activateEvt: |
break; |
case app4Evt: |
if ((myEvent.message << 31) == 0) { /* Suspend */ |
yieldTime = 30; |
HideWindow((WindowPtr) myWindow); |
} |
else { /* Resume */ |
yieldTime = 0; |
ShowWindow((WindowPtr) myWindow); |
SetPort((WindowPtr) myWindow); |
} |
break; |
default: |
break; |
} |
} |
} |
} |
Copyright © 2003 Apple Computer, Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2003-03-12